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 * Copyright (C) 1996, 1999 by Ralf Baechle 762306a36Sopenharmony_ci * Copyright (C) 2011 MIPS Technologies, Inc. 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci#include <linux/errno.h> 1062306a36Sopenharmony_ci#include <linux/export.h> 1162306a36Sopenharmony_ci#include <asm/asm.h> 1262306a36Sopenharmony_ci#include <asm/asm-offsets.h> 1362306a36Sopenharmony_ci#include <asm/regdef.h> 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#define EX(insn,reg,addr,handler) \ 1662306a36Sopenharmony_ci9: insn reg, addr; \ 1762306a36Sopenharmony_ci .section __ex_table,"a"; \ 1862306a36Sopenharmony_ci PTR_WD 9b, handler; \ 1962306a36Sopenharmony_ci .previous 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci/* 2262306a36Sopenharmony_ci * Returns: -EFAULT if exception before terminator, N if the entire 2362306a36Sopenharmony_ci * buffer filled, else strlen. 2462306a36Sopenharmony_ci */ 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci/* 2762306a36Sopenharmony_ci * Ugly special case have to check: we might get passed a user space 2862306a36Sopenharmony_ci * pointer which wraps into the kernel space. We don't deal with that. If 2962306a36Sopenharmony_ci * it happens at most some bytes of the exceptions handlers will be copied. 3062306a36Sopenharmony_ci */ 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ciLEAF(__strncpy_from_user_asm) 3362306a36Sopenharmony_ci move t0, zero 3462306a36Sopenharmony_ci move v1, a1 3562306a36Sopenharmony_ci#ifdef CONFIG_EVA 3662306a36Sopenharmony_ci .set push 3762306a36Sopenharmony_ci .set eva 3862306a36Sopenharmony_ci1: EX(lbue, v0, (v1), .Lfault) 3962306a36Sopenharmony_ci .set pop 4062306a36Sopenharmony_ci#else 4162306a36Sopenharmony_ci1: EX(lbu, v0, (v1), .Lfault) 4262306a36Sopenharmony_ci#endif 4362306a36Sopenharmony_ci PTR_ADDIU v1, 1 4462306a36Sopenharmony_ci R10KCBARRIER(0(ra)) 4562306a36Sopenharmony_ci sb v0, (a0) 4662306a36Sopenharmony_ci beqz v0, 2f 4762306a36Sopenharmony_ci PTR_ADDIU t0, 1 4862306a36Sopenharmony_ci PTR_ADDIU a0, 1 4962306a36Sopenharmony_ci bne t0, a2, 1b 5062306a36Sopenharmony_ci2: PTR_ADDU v0, a1, t0 5162306a36Sopenharmony_ci xor v0, a1 5262306a36Sopenharmony_ci bltz v0, .Lfault 5362306a36Sopenharmony_ci move v0, t0 5462306a36Sopenharmony_ci jr ra # return n 5562306a36Sopenharmony_ci END(__strncpy_from_user_asm) 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci.Lfault: 5862306a36Sopenharmony_ci li v0, -EFAULT 5962306a36Sopenharmony_ci jr ra 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci .section __ex_table,"a" 6262306a36Sopenharmony_ci PTR_WD 1b, .Lfault 6362306a36Sopenharmony_ci .previous 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci EXPORT_SYMBOL(__strncpy_from_user_asm) 66