162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public 362306a36Sopenharmony_ci * License. See the file "COPYING" in the main directory of this archive 462306a36Sopenharmony_ci * for more details. 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Unified implementation of memcpy, memmove and the __copy_user backend. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Copyright (C) 1998, 99, 2000, 01, 2002 Ralf Baechle (ralf@gnu.org) 962306a36Sopenharmony_ci * Copyright (C) 1999, 2000, 01, 2002 Silicon Graphics, Inc. 1062306a36Sopenharmony_ci * Copyright (C) 2002 Broadcom, Inc. 1162306a36Sopenharmony_ci * memcpy/copy_user author: Mark Vandevoorde 1262306a36Sopenharmony_ci * Copyright (C) 2007 Maciej W. Rozycki 1362306a36Sopenharmony_ci * Copyright (C) 2014 Imagination Technologies Ltd. 1462306a36Sopenharmony_ci * 1562306a36Sopenharmony_ci * Mnemonic names for arguments to memcpy/__copy_user 1662306a36Sopenharmony_ci */ 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci/* 1962306a36Sopenharmony_ci * Hack to resolve longstanding prefetch issue 2062306a36Sopenharmony_ci * 2162306a36Sopenharmony_ci * Prefetching may be fatal on some systems if we're prefetching beyond the 2262306a36Sopenharmony_ci * end of memory on some systems. It's also a seriously bad idea on non 2362306a36Sopenharmony_ci * dma-coherent systems. 2462306a36Sopenharmony_ci */ 2562306a36Sopenharmony_ci#ifdef CONFIG_DMA_NONCOHERENT 2662306a36Sopenharmony_ci#undef CONFIG_CPU_HAS_PREFETCH 2762306a36Sopenharmony_ci#endif 2862306a36Sopenharmony_ci#ifdef CONFIG_MIPS_MALTA 2962306a36Sopenharmony_ci#undef CONFIG_CPU_HAS_PREFETCH 3062306a36Sopenharmony_ci#endif 3162306a36Sopenharmony_ci#ifdef CONFIG_CPU_MIPSR6 3262306a36Sopenharmony_ci#undef CONFIG_CPU_HAS_PREFETCH 3362306a36Sopenharmony_ci#endif 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci#include <linux/export.h> 3662306a36Sopenharmony_ci#include <asm/asm.h> 3762306a36Sopenharmony_ci#include <asm/asm-offsets.h> 3862306a36Sopenharmony_ci#include <asm/regdef.h> 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci#define dst a0 4162306a36Sopenharmony_ci#define src a1 4262306a36Sopenharmony_ci#define len a2 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci/* 4562306a36Sopenharmony_ci * Spec 4662306a36Sopenharmony_ci * 4762306a36Sopenharmony_ci * memcpy copies len bytes from src to dst and sets v0 to dst. 4862306a36Sopenharmony_ci * It assumes that 4962306a36Sopenharmony_ci * - src and dst don't overlap 5062306a36Sopenharmony_ci * - src is readable 5162306a36Sopenharmony_ci * - dst is writable 5262306a36Sopenharmony_ci * memcpy uses the standard calling convention 5362306a36Sopenharmony_ci * 5462306a36Sopenharmony_ci * __copy_user copies up to len bytes from src to dst and sets a2 (len) to 5562306a36Sopenharmony_ci * the number of uncopied bytes due to an exception caused by a read or write. 5662306a36Sopenharmony_ci * __copy_user assumes that src and dst don't overlap, and that the call is 5762306a36Sopenharmony_ci * implementing one of the following: 5862306a36Sopenharmony_ci * copy_to_user 5962306a36Sopenharmony_ci * - src is readable (no exceptions when reading src) 6062306a36Sopenharmony_ci * copy_from_user 6162306a36Sopenharmony_ci * - dst is writable (no exceptions when writing dst) 6262306a36Sopenharmony_ci * __copy_user uses a non-standard calling convention; see 6362306a36Sopenharmony_ci * include/asm-mips/uaccess.h 6462306a36Sopenharmony_ci * 6562306a36Sopenharmony_ci * When an exception happens on a load, the handler must 6662306a36Sopenharmony_ci # ensure that all of the destination buffer is overwritten to prevent 6762306a36Sopenharmony_ci * leaking information to user mode programs. 6862306a36Sopenharmony_ci */ 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci/* 7162306a36Sopenharmony_ci * Implementation 7262306a36Sopenharmony_ci */ 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci/* 7562306a36Sopenharmony_ci * The exception handler for loads requires that: 7662306a36Sopenharmony_ci * 1- AT contain the address of the byte just past the end of the source 7762306a36Sopenharmony_ci * of the copy, 7862306a36Sopenharmony_ci * 2- src_entry <= src < AT, and 7962306a36Sopenharmony_ci * 3- (dst - src) == (dst_entry - src_entry), 8062306a36Sopenharmony_ci * The _entry suffix denotes values when __copy_user was called. 8162306a36Sopenharmony_ci * 8262306a36Sopenharmony_ci * (1) is set up up by uaccess.h and maintained by not writing AT in copy_user 8362306a36Sopenharmony_ci * (2) is met by incrementing src by the number of bytes copied 8462306a36Sopenharmony_ci * (3) is met by not doing loads between a pair of increments of dst and src 8562306a36Sopenharmony_ci * 8662306a36Sopenharmony_ci * The exception handlers for stores adjust len (if necessary) and return. 8762306a36Sopenharmony_ci * These handlers do not need to overwrite any data. 8862306a36Sopenharmony_ci * 8962306a36Sopenharmony_ci * For __rmemcpy and memmove an exception is always a kernel bug, therefore 9062306a36Sopenharmony_ci * they're not protected. 9162306a36Sopenharmony_ci */ 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci/* Instruction type */ 9462306a36Sopenharmony_ci#define LD_INSN 1 9562306a36Sopenharmony_ci#define ST_INSN 2 9662306a36Sopenharmony_ci/* Pretech type */ 9762306a36Sopenharmony_ci#define SRC_PREFETCH 1 9862306a36Sopenharmony_ci#define DST_PREFETCH 2 9962306a36Sopenharmony_ci#define LEGACY_MODE 1 10062306a36Sopenharmony_ci#define EVA_MODE 2 10162306a36Sopenharmony_ci#define USEROP 1 10262306a36Sopenharmony_ci#define KERNELOP 2 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci/* 10562306a36Sopenharmony_ci * Wrapper to add an entry in the exception table 10662306a36Sopenharmony_ci * in case the insn causes a memory exception. 10762306a36Sopenharmony_ci * Arguments: 10862306a36Sopenharmony_ci * insn : Load/store instruction 10962306a36Sopenharmony_ci * type : Instruction type 11062306a36Sopenharmony_ci * reg : Register 11162306a36Sopenharmony_ci * addr : Address 11262306a36Sopenharmony_ci * handler : Exception handler 11362306a36Sopenharmony_ci */ 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci#define EXC(insn, type, reg, addr, handler) \ 11662306a36Sopenharmony_ci .if \mode == LEGACY_MODE; \ 11762306a36Sopenharmony_ci9: insn reg, addr; \ 11862306a36Sopenharmony_ci .section __ex_table,"a"; \ 11962306a36Sopenharmony_ci PTR_WD 9b, handler; \ 12062306a36Sopenharmony_ci .previous; \ 12162306a36Sopenharmony_ci /* This is assembled in EVA mode */ \ 12262306a36Sopenharmony_ci .else; \ 12362306a36Sopenharmony_ci /* If loading from user or storing to user */ \ 12462306a36Sopenharmony_ci .if ((\from == USEROP) && (type == LD_INSN)) || \ 12562306a36Sopenharmony_ci ((\to == USEROP) && (type == ST_INSN)); \ 12662306a36Sopenharmony_ci9: __BUILD_EVA_INSN(insn##e, reg, addr); \ 12762306a36Sopenharmony_ci .section __ex_table,"a"; \ 12862306a36Sopenharmony_ci PTR_WD 9b, handler; \ 12962306a36Sopenharmony_ci .previous; \ 13062306a36Sopenharmony_ci .else; \ 13162306a36Sopenharmony_ci /* \ 13262306a36Sopenharmony_ci * Still in EVA, but no need for \ 13362306a36Sopenharmony_ci * exception handler or EVA insn \ 13462306a36Sopenharmony_ci */ \ 13562306a36Sopenharmony_ci insn reg, addr; \ 13662306a36Sopenharmony_ci .endif; \ 13762306a36Sopenharmony_ci .endif 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci/* 14062306a36Sopenharmony_ci * Only on the 64-bit kernel we can made use of 64-bit registers. 14162306a36Sopenharmony_ci */ 14262306a36Sopenharmony_ci#ifdef CONFIG_64BIT 14362306a36Sopenharmony_ci#define USE_DOUBLE 14462306a36Sopenharmony_ci#endif 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci#ifdef USE_DOUBLE 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci#define LOADK ld /* No exception */ 14962306a36Sopenharmony_ci#define LOAD(reg, addr, handler) EXC(ld, LD_INSN, reg, addr, handler) 15062306a36Sopenharmony_ci#define LOADL(reg, addr, handler) EXC(ldl, LD_INSN, reg, addr, handler) 15162306a36Sopenharmony_ci#define LOADR(reg, addr, handler) EXC(ldr, LD_INSN, reg, addr, handler) 15262306a36Sopenharmony_ci#define STOREL(reg, addr, handler) EXC(sdl, ST_INSN, reg, addr, handler) 15362306a36Sopenharmony_ci#define STORER(reg, addr, handler) EXC(sdr, ST_INSN, reg, addr, handler) 15462306a36Sopenharmony_ci#define STORE(reg, addr, handler) EXC(sd, ST_INSN, reg, addr, handler) 15562306a36Sopenharmony_ci#define ADD daddu 15662306a36Sopenharmony_ci#define SUB dsubu 15762306a36Sopenharmony_ci#define SRL dsrl 15862306a36Sopenharmony_ci#define SRA dsra 15962306a36Sopenharmony_ci#define SLL dsll 16062306a36Sopenharmony_ci#define SLLV dsllv 16162306a36Sopenharmony_ci#define SRLV dsrlv 16262306a36Sopenharmony_ci#define NBYTES 8 16362306a36Sopenharmony_ci#define LOG_NBYTES 3 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci/* 16662306a36Sopenharmony_ci * As we are sharing code base with the mips32 tree (which use the o32 ABI 16762306a36Sopenharmony_ci * register definitions). We need to redefine the register definitions from 16862306a36Sopenharmony_ci * the n64 ABI register naming to the o32 ABI register naming. 16962306a36Sopenharmony_ci */ 17062306a36Sopenharmony_ci#undef t0 17162306a36Sopenharmony_ci#undef t1 17262306a36Sopenharmony_ci#undef t2 17362306a36Sopenharmony_ci#undef t3 17462306a36Sopenharmony_ci#define t0 $8 17562306a36Sopenharmony_ci#define t1 $9 17662306a36Sopenharmony_ci#define t2 $10 17762306a36Sopenharmony_ci#define t3 $11 17862306a36Sopenharmony_ci#define t4 $12 17962306a36Sopenharmony_ci#define t5 $13 18062306a36Sopenharmony_ci#define t6 $14 18162306a36Sopenharmony_ci#define t7 $15 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci#else 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci#define LOADK lw /* No exception */ 18662306a36Sopenharmony_ci#define LOAD(reg, addr, handler) EXC(lw, LD_INSN, reg, addr, handler) 18762306a36Sopenharmony_ci#define LOADL(reg, addr, handler) EXC(lwl, LD_INSN, reg, addr, handler) 18862306a36Sopenharmony_ci#define LOADR(reg, addr, handler) EXC(lwr, LD_INSN, reg, addr, handler) 18962306a36Sopenharmony_ci#define STOREL(reg, addr, handler) EXC(swl, ST_INSN, reg, addr, handler) 19062306a36Sopenharmony_ci#define STORER(reg, addr, handler) EXC(swr, ST_INSN, reg, addr, handler) 19162306a36Sopenharmony_ci#define STORE(reg, addr, handler) EXC(sw, ST_INSN, reg, addr, handler) 19262306a36Sopenharmony_ci#define ADD addu 19362306a36Sopenharmony_ci#define SUB subu 19462306a36Sopenharmony_ci#define SRL srl 19562306a36Sopenharmony_ci#define SLL sll 19662306a36Sopenharmony_ci#define SRA sra 19762306a36Sopenharmony_ci#define SLLV sllv 19862306a36Sopenharmony_ci#define SRLV srlv 19962306a36Sopenharmony_ci#define NBYTES 4 20062306a36Sopenharmony_ci#define LOG_NBYTES 2 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci#endif /* USE_DOUBLE */ 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci#define LOADB(reg, addr, handler) EXC(lb, LD_INSN, reg, addr, handler) 20562306a36Sopenharmony_ci#define STOREB(reg, addr, handler) EXC(sb, ST_INSN, reg, addr, handler) 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci#ifdef CONFIG_CPU_HAS_PREFETCH 20862306a36Sopenharmony_ci# define _PREF(hint, addr, type) \ 20962306a36Sopenharmony_ci .if \mode == LEGACY_MODE; \ 21062306a36Sopenharmony_ci kernel_pref(hint, addr); \ 21162306a36Sopenharmony_ci .else; \ 21262306a36Sopenharmony_ci .if ((\from == USEROP) && (type == SRC_PREFETCH)) || \ 21362306a36Sopenharmony_ci ((\to == USEROP) && (type == DST_PREFETCH)); \ 21462306a36Sopenharmony_ci /* \ 21562306a36Sopenharmony_ci * PREFE has only 9 bits for the offset \ 21662306a36Sopenharmony_ci * compared to PREF which has 16, so it may \ 21762306a36Sopenharmony_ci * need to use the $at register but this \ 21862306a36Sopenharmony_ci * register should remain intact because it's \ 21962306a36Sopenharmony_ci * used later on. Therefore use $v1. \ 22062306a36Sopenharmony_ci */ \ 22162306a36Sopenharmony_ci .set at=v1; \ 22262306a36Sopenharmony_ci user_pref(hint, addr); \ 22362306a36Sopenharmony_ci .set noat; \ 22462306a36Sopenharmony_ci .else; \ 22562306a36Sopenharmony_ci kernel_pref(hint, addr); \ 22662306a36Sopenharmony_ci .endif; \ 22762306a36Sopenharmony_ci .endif 22862306a36Sopenharmony_ci#else 22962306a36Sopenharmony_ci# define _PREF(hint, addr, type) 23062306a36Sopenharmony_ci#endif 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci#define PREFS(hint, addr) _PREF(hint, addr, SRC_PREFETCH) 23362306a36Sopenharmony_ci#define PREFD(hint, addr) _PREF(hint, addr, DST_PREFETCH) 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci#ifdef CONFIG_CPU_LITTLE_ENDIAN 23662306a36Sopenharmony_ci#define LDFIRST LOADR 23762306a36Sopenharmony_ci#define LDREST LOADL 23862306a36Sopenharmony_ci#define STFIRST STORER 23962306a36Sopenharmony_ci#define STREST STOREL 24062306a36Sopenharmony_ci#define SHIFT_DISCARD SLLV 24162306a36Sopenharmony_ci#else 24262306a36Sopenharmony_ci#define LDFIRST LOADL 24362306a36Sopenharmony_ci#define LDREST LOADR 24462306a36Sopenharmony_ci#define STFIRST STOREL 24562306a36Sopenharmony_ci#define STREST STORER 24662306a36Sopenharmony_ci#define SHIFT_DISCARD SRLV 24762306a36Sopenharmony_ci#endif 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci#define FIRST(unit) ((unit)*NBYTES) 25062306a36Sopenharmony_ci#define REST(unit) (FIRST(unit)+NBYTES-1) 25162306a36Sopenharmony_ci#define UNIT(unit) FIRST(unit) 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci#define ADDRMASK (NBYTES-1) 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci .text 25662306a36Sopenharmony_ci .set noreorder 25762306a36Sopenharmony_ci#ifndef CONFIG_CPU_DADDI_WORKAROUNDS 25862306a36Sopenharmony_ci .set noat 25962306a36Sopenharmony_ci#else 26062306a36Sopenharmony_ci .set at=v1 26162306a36Sopenharmony_ci#endif 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci .align 5 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci /* 26662306a36Sopenharmony_ci * Macro to build the __copy_user common code 26762306a36Sopenharmony_ci * Arguments: 26862306a36Sopenharmony_ci * mode : LEGACY_MODE or EVA_MODE 26962306a36Sopenharmony_ci * from : Source operand. USEROP or KERNELOP 27062306a36Sopenharmony_ci * to : Destination operand. USEROP or KERNELOP 27162306a36Sopenharmony_ci */ 27262306a36Sopenharmony_ci .macro __BUILD_COPY_USER mode, from, to 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci /* initialize __memcpy if this the first time we execute this macro */ 27562306a36Sopenharmony_ci .ifnotdef __memcpy 27662306a36Sopenharmony_ci .set __memcpy, 1 27762306a36Sopenharmony_ci .hidden __memcpy /* make sure it does not leak */ 27862306a36Sopenharmony_ci .endif 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci /* 28162306a36Sopenharmony_ci * Note: dst & src may be unaligned, len may be 0 28262306a36Sopenharmony_ci * Temps 28362306a36Sopenharmony_ci */ 28462306a36Sopenharmony_ci#define rem t8 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci R10KCBARRIER(0(ra)) 28762306a36Sopenharmony_ci /* 28862306a36Sopenharmony_ci * The "issue break"s below are very approximate. 28962306a36Sopenharmony_ci * Issue delays for dcache fills will perturb the schedule, as will 29062306a36Sopenharmony_ci * load queue full replay traps, etc. 29162306a36Sopenharmony_ci * 29262306a36Sopenharmony_ci * If len < NBYTES use byte operations. 29362306a36Sopenharmony_ci */ 29462306a36Sopenharmony_ci PREFS( 0, 0(src) ) 29562306a36Sopenharmony_ci PREFD( 1, 0(dst) ) 29662306a36Sopenharmony_ci sltu t2, len, NBYTES 29762306a36Sopenharmony_ci and t1, dst, ADDRMASK 29862306a36Sopenharmony_ci PREFS( 0, 1*32(src) ) 29962306a36Sopenharmony_ci PREFD( 1, 1*32(dst) ) 30062306a36Sopenharmony_ci bnez t2, .Lcopy_bytes_checklen\@ 30162306a36Sopenharmony_ci and t0, src, ADDRMASK 30262306a36Sopenharmony_ci PREFS( 0, 2*32(src) ) 30362306a36Sopenharmony_ci PREFD( 1, 2*32(dst) ) 30462306a36Sopenharmony_ci#ifndef CONFIG_CPU_NO_LOAD_STORE_LR 30562306a36Sopenharmony_ci bnez t1, .Ldst_unaligned\@ 30662306a36Sopenharmony_ci nop 30762306a36Sopenharmony_ci bnez t0, .Lsrc_unaligned_dst_aligned\@ 30862306a36Sopenharmony_ci#else /* CONFIG_CPU_NO_LOAD_STORE_LR */ 30962306a36Sopenharmony_ci or t0, t0, t1 31062306a36Sopenharmony_ci bnez t0, .Lcopy_unaligned_bytes\@ 31162306a36Sopenharmony_ci#endif /* CONFIG_CPU_NO_LOAD_STORE_LR */ 31262306a36Sopenharmony_ci /* 31362306a36Sopenharmony_ci * use delay slot for fall-through 31462306a36Sopenharmony_ci * src and dst are aligned; need to compute rem 31562306a36Sopenharmony_ci */ 31662306a36Sopenharmony_ci.Lboth_aligned\@: 31762306a36Sopenharmony_ci SRL t0, len, LOG_NBYTES+3 # +3 for 8 units/iter 31862306a36Sopenharmony_ci beqz t0, .Lcleanup_both_aligned\@ # len < 8*NBYTES 31962306a36Sopenharmony_ci and rem, len, (8*NBYTES-1) # rem = len % (8*NBYTES) 32062306a36Sopenharmony_ci PREFS( 0, 3*32(src) ) 32162306a36Sopenharmony_ci PREFD( 1, 3*32(dst) ) 32262306a36Sopenharmony_ci .align 4 32362306a36Sopenharmony_ci1: 32462306a36Sopenharmony_ci R10KCBARRIER(0(ra)) 32562306a36Sopenharmony_ci LOAD(t0, UNIT(0)(src), .Ll_exc\@) 32662306a36Sopenharmony_ci LOAD(t1, UNIT(1)(src), .Ll_exc_copy\@) 32762306a36Sopenharmony_ci LOAD(t2, UNIT(2)(src), .Ll_exc_copy\@) 32862306a36Sopenharmony_ci LOAD(t3, UNIT(3)(src), .Ll_exc_copy\@) 32962306a36Sopenharmony_ci SUB len, len, 8*NBYTES 33062306a36Sopenharmony_ci LOAD(t4, UNIT(4)(src), .Ll_exc_copy\@) 33162306a36Sopenharmony_ci LOAD(t7, UNIT(5)(src), .Ll_exc_copy\@) 33262306a36Sopenharmony_ci STORE(t0, UNIT(0)(dst), .Ls_exc_p8u\@) 33362306a36Sopenharmony_ci STORE(t1, UNIT(1)(dst), .Ls_exc_p7u\@) 33462306a36Sopenharmony_ci LOAD(t0, UNIT(6)(src), .Ll_exc_copy\@) 33562306a36Sopenharmony_ci LOAD(t1, UNIT(7)(src), .Ll_exc_copy\@) 33662306a36Sopenharmony_ci ADD src, src, 8*NBYTES 33762306a36Sopenharmony_ci ADD dst, dst, 8*NBYTES 33862306a36Sopenharmony_ci STORE(t2, UNIT(-6)(dst), .Ls_exc_p6u\@) 33962306a36Sopenharmony_ci STORE(t3, UNIT(-5)(dst), .Ls_exc_p5u\@) 34062306a36Sopenharmony_ci STORE(t4, UNIT(-4)(dst), .Ls_exc_p4u\@) 34162306a36Sopenharmony_ci STORE(t7, UNIT(-3)(dst), .Ls_exc_p3u\@) 34262306a36Sopenharmony_ci STORE(t0, UNIT(-2)(dst), .Ls_exc_p2u\@) 34362306a36Sopenharmony_ci STORE(t1, UNIT(-1)(dst), .Ls_exc_p1u\@) 34462306a36Sopenharmony_ci PREFS( 0, 8*32(src) ) 34562306a36Sopenharmony_ci PREFD( 1, 8*32(dst) ) 34662306a36Sopenharmony_ci bne len, rem, 1b 34762306a36Sopenharmony_ci nop 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci /* 35062306a36Sopenharmony_ci * len == rem == the number of bytes left to copy < 8*NBYTES 35162306a36Sopenharmony_ci */ 35262306a36Sopenharmony_ci.Lcleanup_both_aligned\@: 35362306a36Sopenharmony_ci beqz len, .Ldone\@ 35462306a36Sopenharmony_ci sltu t0, len, 4*NBYTES 35562306a36Sopenharmony_ci bnez t0, .Lless_than_4units\@ 35662306a36Sopenharmony_ci and rem, len, (NBYTES-1) # rem = len % NBYTES 35762306a36Sopenharmony_ci /* 35862306a36Sopenharmony_ci * len >= 4*NBYTES 35962306a36Sopenharmony_ci */ 36062306a36Sopenharmony_ci LOAD( t0, UNIT(0)(src), .Ll_exc\@) 36162306a36Sopenharmony_ci LOAD( t1, UNIT(1)(src), .Ll_exc_copy\@) 36262306a36Sopenharmony_ci LOAD( t2, UNIT(2)(src), .Ll_exc_copy\@) 36362306a36Sopenharmony_ci LOAD( t3, UNIT(3)(src), .Ll_exc_copy\@) 36462306a36Sopenharmony_ci SUB len, len, 4*NBYTES 36562306a36Sopenharmony_ci ADD src, src, 4*NBYTES 36662306a36Sopenharmony_ci R10KCBARRIER(0(ra)) 36762306a36Sopenharmony_ci STORE(t0, UNIT(0)(dst), .Ls_exc_p4u\@) 36862306a36Sopenharmony_ci STORE(t1, UNIT(1)(dst), .Ls_exc_p3u\@) 36962306a36Sopenharmony_ci STORE(t2, UNIT(2)(dst), .Ls_exc_p2u\@) 37062306a36Sopenharmony_ci STORE(t3, UNIT(3)(dst), .Ls_exc_p1u\@) 37162306a36Sopenharmony_ci .set reorder /* DADDI_WAR */ 37262306a36Sopenharmony_ci ADD dst, dst, 4*NBYTES 37362306a36Sopenharmony_ci beqz len, .Ldone\@ 37462306a36Sopenharmony_ci .set noreorder 37562306a36Sopenharmony_ci.Lless_than_4units\@: 37662306a36Sopenharmony_ci /* 37762306a36Sopenharmony_ci * rem = len % NBYTES 37862306a36Sopenharmony_ci */ 37962306a36Sopenharmony_ci beq rem, len, .Lcopy_bytes\@ 38062306a36Sopenharmony_ci nop 38162306a36Sopenharmony_ci1: 38262306a36Sopenharmony_ci R10KCBARRIER(0(ra)) 38362306a36Sopenharmony_ci LOAD(t0, 0(src), .Ll_exc\@) 38462306a36Sopenharmony_ci ADD src, src, NBYTES 38562306a36Sopenharmony_ci SUB len, len, NBYTES 38662306a36Sopenharmony_ci STORE(t0, 0(dst), .Ls_exc_p1u\@) 38762306a36Sopenharmony_ci .set reorder /* DADDI_WAR */ 38862306a36Sopenharmony_ci ADD dst, dst, NBYTES 38962306a36Sopenharmony_ci bne rem, len, 1b 39062306a36Sopenharmony_ci .set noreorder 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci#ifndef CONFIG_CPU_NO_LOAD_STORE_LR 39362306a36Sopenharmony_ci /* 39462306a36Sopenharmony_ci * src and dst are aligned, need to copy rem bytes (rem < NBYTES) 39562306a36Sopenharmony_ci * A loop would do only a byte at a time with possible branch 39662306a36Sopenharmony_ci * mispredicts. Can't do an explicit LOAD dst,mask,or,STORE 39762306a36Sopenharmony_ci * because can't assume read-access to dst. Instead, use 39862306a36Sopenharmony_ci * STREST dst, which doesn't require read access to dst. 39962306a36Sopenharmony_ci * 40062306a36Sopenharmony_ci * This code should perform better than a simple loop on modern, 40162306a36Sopenharmony_ci * wide-issue mips processors because the code has fewer branches and 40262306a36Sopenharmony_ci * more instruction-level parallelism. 40362306a36Sopenharmony_ci */ 40462306a36Sopenharmony_ci#define bits t2 40562306a36Sopenharmony_ci beqz len, .Ldone\@ 40662306a36Sopenharmony_ci ADD t1, dst, len # t1 is just past last byte of dst 40762306a36Sopenharmony_ci li bits, 8*NBYTES 40862306a36Sopenharmony_ci SLL rem, len, 3 # rem = number of bits to keep 40962306a36Sopenharmony_ci LOAD(t0, 0(src), .Ll_exc\@) 41062306a36Sopenharmony_ci SUB bits, bits, rem # bits = number of bits to discard 41162306a36Sopenharmony_ci SHIFT_DISCARD t0, t0, bits 41262306a36Sopenharmony_ci STREST(t0, -1(t1), .Ls_exc\@) 41362306a36Sopenharmony_ci jr ra 41462306a36Sopenharmony_ci move len, zero 41562306a36Sopenharmony_ci.Ldst_unaligned\@: 41662306a36Sopenharmony_ci /* 41762306a36Sopenharmony_ci * dst is unaligned 41862306a36Sopenharmony_ci * t0 = src & ADDRMASK 41962306a36Sopenharmony_ci * t1 = dst & ADDRMASK; T1 > 0 42062306a36Sopenharmony_ci * len >= NBYTES 42162306a36Sopenharmony_ci * 42262306a36Sopenharmony_ci * Copy enough bytes to align dst 42362306a36Sopenharmony_ci * Set match = (src and dst have same alignment) 42462306a36Sopenharmony_ci */ 42562306a36Sopenharmony_ci#define match rem 42662306a36Sopenharmony_ci LDFIRST(t3, FIRST(0)(src), .Ll_exc\@) 42762306a36Sopenharmony_ci ADD t2, zero, NBYTES 42862306a36Sopenharmony_ci LDREST(t3, REST(0)(src), .Ll_exc_copy\@) 42962306a36Sopenharmony_ci SUB t2, t2, t1 # t2 = number of bytes copied 43062306a36Sopenharmony_ci xor match, t0, t1 43162306a36Sopenharmony_ci R10KCBARRIER(0(ra)) 43262306a36Sopenharmony_ci STFIRST(t3, FIRST(0)(dst), .Ls_exc\@) 43362306a36Sopenharmony_ci beq len, t2, .Ldone\@ 43462306a36Sopenharmony_ci SUB len, len, t2 43562306a36Sopenharmony_ci ADD dst, dst, t2 43662306a36Sopenharmony_ci beqz match, .Lboth_aligned\@ 43762306a36Sopenharmony_ci ADD src, src, t2 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci.Lsrc_unaligned_dst_aligned\@: 44062306a36Sopenharmony_ci SRL t0, len, LOG_NBYTES+2 # +2 for 4 units/iter 44162306a36Sopenharmony_ci PREFS( 0, 3*32(src) ) 44262306a36Sopenharmony_ci beqz t0, .Lcleanup_src_unaligned\@ 44362306a36Sopenharmony_ci and rem, len, (4*NBYTES-1) # rem = len % 4*NBYTES 44462306a36Sopenharmony_ci PREFD( 1, 3*32(dst) ) 44562306a36Sopenharmony_ci1: 44662306a36Sopenharmony_ci/* 44762306a36Sopenharmony_ci * Avoid consecutive LD*'s to the same register since some mips 44862306a36Sopenharmony_ci * implementations can't issue them in the same cycle. 44962306a36Sopenharmony_ci * It's OK to load FIRST(N+1) before REST(N) because the two addresses 45062306a36Sopenharmony_ci * are to the same unit (unless src is aligned, but it's not). 45162306a36Sopenharmony_ci */ 45262306a36Sopenharmony_ci R10KCBARRIER(0(ra)) 45362306a36Sopenharmony_ci LDFIRST(t0, FIRST(0)(src), .Ll_exc\@) 45462306a36Sopenharmony_ci LDFIRST(t1, FIRST(1)(src), .Ll_exc_copy\@) 45562306a36Sopenharmony_ci SUB len, len, 4*NBYTES 45662306a36Sopenharmony_ci LDREST(t0, REST(0)(src), .Ll_exc_copy\@) 45762306a36Sopenharmony_ci LDREST(t1, REST(1)(src), .Ll_exc_copy\@) 45862306a36Sopenharmony_ci LDFIRST(t2, FIRST(2)(src), .Ll_exc_copy\@) 45962306a36Sopenharmony_ci LDFIRST(t3, FIRST(3)(src), .Ll_exc_copy\@) 46062306a36Sopenharmony_ci LDREST(t2, REST(2)(src), .Ll_exc_copy\@) 46162306a36Sopenharmony_ci LDREST(t3, REST(3)(src), .Ll_exc_copy\@) 46262306a36Sopenharmony_ci PREFS( 0, 9*32(src) ) # 0 is PREF_LOAD (not streamed) 46362306a36Sopenharmony_ci ADD src, src, 4*NBYTES 46462306a36Sopenharmony_ci#ifdef CONFIG_CPU_SB1 46562306a36Sopenharmony_ci nop # improves slotting 46662306a36Sopenharmony_ci#endif 46762306a36Sopenharmony_ci STORE(t0, UNIT(0)(dst), .Ls_exc_p4u\@) 46862306a36Sopenharmony_ci STORE(t1, UNIT(1)(dst), .Ls_exc_p3u\@) 46962306a36Sopenharmony_ci STORE(t2, UNIT(2)(dst), .Ls_exc_p2u\@) 47062306a36Sopenharmony_ci STORE(t3, UNIT(3)(dst), .Ls_exc_p1u\@) 47162306a36Sopenharmony_ci PREFD( 1, 9*32(dst) ) # 1 is PREF_STORE (not streamed) 47262306a36Sopenharmony_ci .set reorder /* DADDI_WAR */ 47362306a36Sopenharmony_ci ADD dst, dst, 4*NBYTES 47462306a36Sopenharmony_ci bne len, rem, 1b 47562306a36Sopenharmony_ci .set noreorder 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ci.Lcleanup_src_unaligned\@: 47862306a36Sopenharmony_ci beqz len, .Ldone\@ 47962306a36Sopenharmony_ci and rem, len, NBYTES-1 # rem = len % NBYTES 48062306a36Sopenharmony_ci beq rem, len, .Lcopy_bytes\@ 48162306a36Sopenharmony_ci nop 48262306a36Sopenharmony_ci1: 48362306a36Sopenharmony_ci R10KCBARRIER(0(ra)) 48462306a36Sopenharmony_ci LDFIRST(t0, FIRST(0)(src), .Ll_exc\@) 48562306a36Sopenharmony_ci LDREST(t0, REST(0)(src), .Ll_exc_copy\@) 48662306a36Sopenharmony_ci ADD src, src, NBYTES 48762306a36Sopenharmony_ci SUB len, len, NBYTES 48862306a36Sopenharmony_ci STORE(t0, 0(dst), .Ls_exc_p1u\@) 48962306a36Sopenharmony_ci .set reorder /* DADDI_WAR */ 49062306a36Sopenharmony_ci ADD dst, dst, NBYTES 49162306a36Sopenharmony_ci bne len, rem, 1b 49262306a36Sopenharmony_ci .set noreorder 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci#endif /* !CONFIG_CPU_NO_LOAD_STORE_LR */ 49562306a36Sopenharmony_ci.Lcopy_bytes_checklen\@: 49662306a36Sopenharmony_ci beqz len, .Ldone\@ 49762306a36Sopenharmony_ci nop 49862306a36Sopenharmony_ci.Lcopy_bytes\@: 49962306a36Sopenharmony_ci /* 0 < len < NBYTES */ 50062306a36Sopenharmony_ci R10KCBARRIER(0(ra)) 50162306a36Sopenharmony_ci#define COPY_BYTE(N) \ 50262306a36Sopenharmony_ci LOADB(t0, N(src), .Ll_exc\@); \ 50362306a36Sopenharmony_ci SUB len, len, 1; \ 50462306a36Sopenharmony_ci beqz len, .Ldone\@; \ 50562306a36Sopenharmony_ci STOREB(t0, N(dst), .Ls_exc_p1\@) 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci COPY_BYTE(0) 50862306a36Sopenharmony_ci COPY_BYTE(1) 50962306a36Sopenharmony_ci#ifdef USE_DOUBLE 51062306a36Sopenharmony_ci COPY_BYTE(2) 51162306a36Sopenharmony_ci COPY_BYTE(3) 51262306a36Sopenharmony_ci COPY_BYTE(4) 51362306a36Sopenharmony_ci COPY_BYTE(5) 51462306a36Sopenharmony_ci#endif 51562306a36Sopenharmony_ci LOADB(t0, NBYTES-2(src), .Ll_exc\@) 51662306a36Sopenharmony_ci SUB len, len, 1 51762306a36Sopenharmony_ci jr ra 51862306a36Sopenharmony_ci STOREB(t0, NBYTES-2(dst), .Ls_exc_p1\@) 51962306a36Sopenharmony_ci.Ldone\@: 52062306a36Sopenharmony_ci jr ra 52162306a36Sopenharmony_ci nop 52262306a36Sopenharmony_ci 52362306a36Sopenharmony_ci#ifdef CONFIG_CPU_NO_LOAD_STORE_LR 52462306a36Sopenharmony_ci.Lcopy_unaligned_bytes\@: 52562306a36Sopenharmony_ci1: 52662306a36Sopenharmony_ci COPY_BYTE(0) 52762306a36Sopenharmony_ci COPY_BYTE(1) 52862306a36Sopenharmony_ci COPY_BYTE(2) 52962306a36Sopenharmony_ci COPY_BYTE(3) 53062306a36Sopenharmony_ci COPY_BYTE(4) 53162306a36Sopenharmony_ci COPY_BYTE(5) 53262306a36Sopenharmony_ci COPY_BYTE(6) 53362306a36Sopenharmony_ci COPY_BYTE(7) 53462306a36Sopenharmony_ci ADD src, src, 8 53562306a36Sopenharmony_ci b 1b 53662306a36Sopenharmony_ci ADD dst, dst, 8 53762306a36Sopenharmony_ci#endif /* CONFIG_CPU_NO_LOAD_STORE_LR */ 53862306a36Sopenharmony_ci .if __memcpy == 1 53962306a36Sopenharmony_ci END(memcpy) 54062306a36Sopenharmony_ci .set __memcpy, 0 54162306a36Sopenharmony_ci .hidden __memcpy 54262306a36Sopenharmony_ci .endif 54362306a36Sopenharmony_ci 54462306a36Sopenharmony_ci.Ll_exc_copy\@: 54562306a36Sopenharmony_ci /* 54662306a36Sopenharmony_ci * Copy bytes from src until faulting load address (or until a 54762306a36Sopenharmony_ci * lb faults) 54862306a36Sopenharmony_ci * 54962306a36Sopenharmony_ci * When reached by a faulting LDFIRST/LDREST, THREAD_BUADDR($28) 55062306a36Sopenharmony_ci * may be more than a byte beyond the last address. 55162306a36Sopenharmony_ci * Hence, the lb below may get an exception. 55262306a36Sopenharmony_ci * 55362306a36Sopenharmony_ci * Assumes src < THREAD_BUADDR($28) 55462306a36Sopenharmony_ci */ 55562306a36Sopenharmony_ci LOADK t0, TI_TASK($28) 55662306a36Sopenharmony_ci nop 55762306a36Sopenharmony_ci LOADK t0, THREAD_BUADDR(t0) 55862306a36Sopenharmony_ci1: 55962306a36Sopenharmony_ci LOADB(t1, 0(src), .Ll_exc\@) 56062306a36Sopenharmony_ci ADD src, src, 1 56162306a36Sopenharmony_ci sb t1, 0(dst) # can't fault -- we're copy_from_user 56262306a36Sopenharmony_ci .set reorder /* DADDI_WAR */ 56362306a36Sopenharmony_ci ADD dst, dst, 1 56462306a36Sopenharmony_ci bne src, t0, 1b 56562306a36Sopenharmony_ci .set noreorder 56662306a36Sopenharmony_ci.Ll_exc\@: 56762306a36Sopenharmony_ci LOADK t0, TI_TASK($28) 56862306a36Sopenharmony_ci nop 56962306a36Sopenharmony_ci LOADK t0, THREAD_BUADDR(t0) # t0 is just past last good address 57062306a36Sopenharmony_ci nop 57162306a36Sopenharmony_ci SUB len, AT, t0 # len number of uncopied bytes 57262306a36Sopenharmony_ci jr ra 57362306a36Sopenharmony_ci nop 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci#define SEXC(n) \ 57662306a36Sopenharmony_ci .set reorder; /* DADDI_WAR */ \ 57762306a36Sopenharmony_ci.Ls_exc_p ## n ## u\@: \ 57862306a36Sopenharmony_ci ADD len, len, n*NBYTES; \ 57962306a36Sopenharmony_ci jr ra; \ 58062306a36Sopenharmony_ci .set noreorder 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ciSEXC(8) 58362306a36Sopenharmony_ciSEXC(7) 58462306a36Sopenharmony_ciSEXC(6) 58562306a36Sopenharmony_ciSEXC(5) 58662306a36Sopenharmony_ciSEXC(4) 58762306a36Sopenharmony_ciSEXC(3) 58862306a36Sopenharmony_ciSEXC(2) 58962306a36Sopenharmony_ciSEXC(1) 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_ci.Ls_exc_p1\@: 59262306a36Sopenharmony_ci .set reorder /* DADDI_WAR */ 59362306a36Sopenharmony_ci ADD len, len, 1 59462306a36Sopenharmony_ci jr ra 59562306a36Sopenharmony_ci .set noreorder 59662306a36Sopenharmony_ci.Ls_exc\@: 59762306a36Sopenharmony_ci jr ra 59862306a36Sopenharmony_ci nop 59962306a36Sopenharmony_ci .endm 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_ci#ifndef CONFIG_HAVE_PLAT_MEMCPY 60262306a36Sopenharmony_ci .align 5 60362306a36Sopenharmony_ciLEAF(memmove) 60462306a36Sopenharmony_ciEXPORT_SYMBOL(memmove) 60562306a36Sopenharmony_ci ADD t0, a0, a2 60662306a36Sopenharmony_ci ADD t1, a1, a2 60762306a36Sopenharmony_ci sltu t0, a1, t0 # dst + len <= src -> memcpy 60862306a36Sopenharmony_ci sltu t1, a0, t1 # dst >= src + len -> memcpy 60962306a36Sopenharmony_ci and t0, t1 61062306a36Sopenharmony_ci beqz t0, .L__memcpy 61162306a36Sopenharmony_ci move v0, a0 /* return value */ 61262306a36Sopenharmony_ci beqz a2, .Lr_out 61362306a36Sopenharmony_ci END(memmove) 61462306a36Sopenharmony_ci 61562306a36Sopenharmony_ci /* fall through to __rmemcpy */ 61662306a36Sopenharmony_ciLEAF(__rmemcpy) /* a0=dst a1=src a2=len */ 61762306a36Sopenharmony_ci sltu t0, a1, a0 61862306a36Sopenharmony_ci beqz t0, .Lr_end_bytes_up # src >= dst 61962306a36Sopenharmony_ci nop 62062306a36Sopenharmony_ci ADD a0, a2 # dst = dst + len 62162306a36Sopenharmony_ci ADD a1, a2 # src = src + len 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_ci.Lr_end_bytes: 62462306a36Sopenharmony_ci R10KCBARRIER(0(ra)) 62562306a36Sopenharmony_ci lb t0, -1(a1) 62662306a36Sopenharmony_ci SUB a2, a2, 0x1 62762306a36Sopenharmony_ci sb t0, -1(a0) 62862306a36Sopenharmony_ci SUB a1, a1, 0x1 62962306a36Sopenharmony_ci .set reorder /* DADDI_WAR */ 63062306a36Sopenharmony_ci SUB a0, a0, 0x1 63162306a36Sopenharmony_ci bnez a2, .Lr_end_bytes 63262306a36Sopenharmony_ci .set noreorder 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci.Lr_out: 63562306a36Sopenharmony_ci jr ra 63662306a36Sopenharmony_ci move a2, zero 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_ci.Lr_end_bytes_up: 63962306a36Sopenharmony_ci R10KCBARRIER(0(ra)) 64062306a36Sopenharmony_ci lb t0, (a1) 64162306a36Sopenharmony_ci SUB a2, a2, 0x1 64262306a36Sopenharmony_ci sb t0, (a0) 64362306a36Sopenharmony_ci ADD a1, a1, 0x1 64462306a36Sopenharmony_ci .set reorder /* DADDI_WAR */ 64562306a36Sopenharmony_ci ADD a0, a0, 0x1 64662306a36Sopenharmony_ci bnez a2, .Lr_end_bytes_up 64762306a36Sopenharmony_ci .set noreorder 64862306a36Sopenharmony_ci 64962306a36Sopenharmony_ci jr ra 65062306a36Sopenharmony_ci move a2, zero 65162306a36Sopenharmony_ci END(__rmemcpy) 65262306a36Sopenharmony_ci 65362306a36Sopenharmony_ci/* 65462306a36Sopenharmony_ci * A combined memcpy/__copy_user 65562306a36Sopenharmony_ci * __copy_user sets len to 0 for success; else to an upper bound of 65662306a36Sopenharmony_ci * the number of uncopied bytes. 65762306a36Sopenharmony_ci * memcpy sets v0 to dst. 65862306a36Sopenharmony_ci */ 65962306a36Sopenharmony_ci .align 5 66062306a36Sopenharmony_ciLEAF(memcpy) /* a0=dst a1=src a2=len */ 66162306a36Sopenharmony_ciEXPORT_SYMBOL(memcpy) 66262306a36Sopenharmony_ci move v0, dst /* return value */ 66362306a36Sopenharmony_ci.L__memcpy: 66462306a36Sopenharmony_ci#ifndef CONFIG_EVA 66562306a36Sopenharmony_ciFEXPORT(__raw_copy_from_user) 66662306a36Sopenharmony_ciEXPORT_SYMBOL(__raw_copy_from_user) 66762306a36Sopenharmony_ciFEXPORT(__raw_copy_to_user) 66862306a36Sopenharmony_ciEXPORT_SYMBOL(__raw_copy_to_user) 66962306a36Sopenharmony_ci#endif 67062306a36Sopenharmony_ci /* Legacy Mode, user <-> user */ 67162306a36Sopenharmony_ci __BUILD_COPY_USER LEGACY_MODE USEROP USEROP 67262306a36Sopenharmony_ci 67362306a36Sopenharmony_ci#endif 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_ci#ifdef CONFIG_EVA 67662306a36Sopenharmony_ci 67762306a36Sopenharmony_ci/* 67862306a36Sopenharmony_ci * For EVA we need distinct symbols for reading and writing to user space. 67962306a36Sopenharmony_ci * This is because we need to use specific EVA instructions to perform the 68062306a36Sopenharmony_ci * virtual <-> physical translation when a virtual address is actually in user 68162306a36Sopenharmony_ci * space 68262306a36Sopenharmony_ci */ 68362306a36Sopenharmony_ci 68462306a36Sopenharmony_ci/* 68562306a36Sopenharmony_ci * __copy_from_user (EVA) 68662306a36Sopenharmony_ci */ 68762306a36Sopenharmony_ci 68862306a36Sopenharmony_ciLEAF(__raw_copy_from_user) 68962306a36Sopenharmony_ciEXPORT_SYMBOL(__raw_copy_from_user) 69062306a36Sopenharmony_ci __BUILD_COPY_USER EVA_MODE USEROP KERNELOP 69162306a36Sopenharmony_ciEND(__raw_copy_from_user) 69262306a36Sopenharmony_ci 69362306a36Sopenharmony_ci 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_ci/* 69662306a36Sopenharmony_ci * __copy_to_user (EVA) 69762306a36Sopenharmony_ci */ 69862306a36Sopenharmony_ci 69962306a36Sopenharmony_ciLEAF(__raw_copy_to_user) 70062306a36Sopenharmony_ciEXPORT_SYMBOL(__raw_copy_to_user) 70162306a36Sopenharmony_ci__BUILD_COPY_USER EVA_MODE KERNELOP USEROP 70262306a36Sopenharmony_ciEND(__raw_copy_to_user) 70362306a36Sopenharmony_ci 70462306a36Sopenharmony_ci#endif 705