Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.9-rc5 147 lines 4.7 kB view raw
1/* 2 * Copyright 2010 Tilera Corporation. All Rights Reserved. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation, version 2. 7 * 8 * This program is distributed in the hope that it will be useful, but 9 * WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or 11 * NON INFRINGEMENT. See the GNU General Public License for 12 * more details. 13 */ 14 15#include <linux/linkage.h> 16#include <asm/errno.h> 17#include <asm/cache.h> 18#include <arch/chip.h> 19 20/* Access user memory, but use MMU to avoid propagating kernel exceptions. */ 21 22/* 23 * strnlen_user_asm takes the pointer in r0, and the length bound in r1. 24 * It returns the length, including the terminating NUL, or zero on exception. 25 * If length is greater than the bound, returns one plus the bound. 26 */ 27STD_ENTRY(strnlen_user_asm) 28 { bz r1, 2f; addi r3, r0, -1 } /* bias down to include NUL */ 291: { lb_u r4, r0; addi r1, r1, -1 } 30 bz r4, 2f 31 { bnzt r1, 1b; addi r0, r0, 1 } 322: { sub r0, r0, r3; jrp lr } 33 STD_ENDPROC(strnlen_user_asm) 34 .pushsection .fixup,"ax" 35strnlen_user_fault: 36 { move r0, zero; jrp lr } 37 ENDPROC(strnlen_user_fault) 38 .section __ex_table,"a" 39 .word 1b, strnlen_user_fault 40 .popsection 41 42/* 43 * strncpy_from_user_asm takes the kernel target pointer in r0, 44 * the userspace source pointer in r1, and the length bound (including 45 * the trailing NUL) in r2. On success, it returns the string length 46 * (not including the trailing NUL), or -EFAULT on failure. 47 */ 48STD_ENTRY(strncpy_from_user_asm) 49 { bz r2, 2f; move r3, r0 } 501: { lb_u r4, r1; addi r1, r1, 1; addi r2, r2, -1 } 51 { sb r0, r4; addi r0, r0, 1 } 52 bz r2, 2f 53 bnzt r4, 1b 54 addi r0, r0, -1 /* don't count the trailing NUL */ 552: { sub r0, r0, r3; jrp lr } 56 STD_ENDPROC(strncpy_from_user_asm) 57 .pushsection .fixup,"ax" 58strncpy_from_user_fault: 59 { movei r0, -EFAULT; jrp lr } 60 ENDPROC(strncpy_from_user_fault) 61 .section __ex_table,"a" 62 .word 1b, strncpy_from_user_fault 63 .popsection 64 65/* 66 * clear_user_asm takes the user target address in r0 and the 67 * number of bytes to zero in r1. 68 * It returns the number of uncopiable bytes (hopefully zero) in r0. 69 * Note that we don't use a separate .fixup section here since we fall 70 * through into the "fixup" code as the last straight-line bundle anyway. 71 */ 72STD_ENTRY(clear_user_asm) 73 { bz r1, 2f; or r2, r0, r1 } 74 andi r2, r2, 3 75 bzt r2, .Lclear_aligned_user_asm 761: { sb r0, zero; addi r0, r0, 1; addi r1, r1, -1 } 77 bnzt r1, 1b 782: { move r0, r1; jrp lr } 79 .pushsection __ex_table,"a" 80 .word 1b, 2b 81 .popsection 82 83.Lclear_aligned_user_asm: 841: { sw r0, zero; addi r0, r0, 4; addi r1, r1, -4 } 85 bnzt r1, 1b 862: { move r0, r1; jrp lr } 87 STD_ENDPROC(clear_user_asm) 88 .pushsection __ex_table,"a" 89 .word 1b, 2b 90 .popsection 91 92/* 93 * flush_user_asm takes the user target address in r0 and the 94 * number of bytes to flush in r1. 95 * It returns the number of unflushable bytes (hopefully zero) in r0. 96 */ 97STD_ENTRY(flush_user_asm) 98 bz r1, 2f 99 { movei r2, L2_CACHE_BYTES; add r1, r0, r1 } 100 { sub r2, zero, r2; addi r1, r1, L2_CACHE_BYTES-1 } 101 { and r0, r0, r2; and r1, r1, r2 } 102 { sub r1, r1, r0 } 1031: { flush r0; addi r1, r1, -CHIP_FLUSH_STRIDE() } 104 { addi r0, r0, CHIP_FLUSH_STRIDE(); bnzt r1, 1b } 1052: { move r0, r1; jrp lr } 106 STD_ENDPROC(flush_user_asm) 107 .pushsection __ex_table,"a" 108 .word 1b, 2b 109 .popsection 110 111/* 112 * inv_user_asm takes the user target address in r0 and the 113 * number of bytes to invalidate in r1. 114 * It returns the number of not inv'able bytes (hopefully zero) in r0. 115 */ 116STD_ENTRY(inv_user_asm) 117 bz r1, 2f 118 { movei r2, L2_CACHE_BYTES; add r1, r0, r1 } 119 { sub r2, zero, r2; addi r1, r1, L2_CACHE_BYTES-1 } 120 { and r0, r0, r2; and r1, r1, r2 } 121 { sub r1, r1, r0 } 1221: { inv r0; addi r1, r1, -CHIP_INV_STRIDE() } 123 { addi r0, r0, CHIP_INV_STRIDE(); bnzt r1, 1b } 1242: { move r0, r1; jrp lr } 125 STD_ENDPROC(inv_user_asm) 126 .pushsection __ex_table,"a" 127 .word 1b, 2b 128 .popsection 129 130/* 131 * finv_user_asm takes the user target address in r0 and the 132 * number of bytes to flush-invalidate in r1. 133 * It returns the number of not finv'able bytes (hopefully zero) in r0. 134 */ 135STD_ENTRY(finv_user_asm) 136 bz r1, 2f 137 { movei r2, L2_CACHE_BYTES; add r1, r0, r1 } 138 { sub r2, zero, r2; addi r1, r1, L2_CACHE_BYTES-1 } 139 { and r0, r0, r2; and r1, r1, r2 } 140 { sub r1, r1, r0 } 1411: { finv r0; addi r1, r1, -CHIP_FINV_STRIDE() } 142 { addi r0, r0, CHIP_FINV_STRIDE(); bnzt r1, 1b } 1432: { move r0, r1; jrp lr } 144 STD_ENDPROC(finv_user_asm) 145 .pushsection __ex_table,"a" 146 .word 1b, 2b 147 .popsection