/* * hal_uspace.c - implementation of Generic User Space Access API for MIPS32 * * Author Mohamed Karaoui (2015) * Alain Greiner (2016) * * Copyright (c) UPMC Sorbonne Universites * * This file is part of ALMOS-MKH.. * * ALMOS-MKH. is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2.0 of the License. * * ALMOS-MKH. is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with ALMOS-MKH.; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include /////////////////////////////////////////// void hal_copy_from_uspace( void * k_dst, void * u_src, uint32_t size ) { uint32_t save_sr; uint32_t i; uint32_t wsize; // number of words uint32_t src = (uint32_t)u_src; uint32_t dst = (uint32_t)k_dst; if( (dst & 0x3) || (src & 0x3) ) wsize = 0; // do it all in bytes else wsize = size >> 2; hal_disable_irq( &save_sr ); for( i = 0 ; i < wsize ; i++ ) // transfer one word per iteration { asm volatile( "mfc2 $15, $1 \n" /* save MMU_MODE */ "ori $14, $0, 0x7 \n" "mtc2 $14, $1 \n" /* MMU_MODE <= DTLB ON */ "lw $13, 0(%0) \n" /* read data from user space */ "mtc2 $15, $1 \n" /* restore MMU_MODE */ "sw $13, 0(%1) \n" /* store data to kernel space */ : : "r"( src ) , "r"( dst ) : "$13","$14","$15", "memory" ); src += 4; dst += 4; } for( i = wsize << 2 ; i < size ; i++ ) // transfer one byte per iteration { asm volatile( "mfc2 $15, $1 \n" /* save MMU_MODE */ "ori $14, $0, 0x7 \n" "mtc2 $14, $1 \n" /* MMU_MODE <= DTLB ON */ "lb $13, 0(%0) \n" /* read data from user space */ "mtc2 $15, $1 \n" /* restore MMU_MODE */ "sb $13, 0(%1) \n" /* store data to kernel space */ : : "r"( src ) , "r"( dst ) : "$13","$14","$15", "memory" ); src += 1; dst += 1; } hal_restore_irq( save_sr ); } // end hal_copy_from_uspace() /////////////////////////////////////////// void hal_copy_to_uspace( void * u_dst, void * k_src, uint32_t size ) { uint32_t save_sr; uint32_t i; uint32_t wsize; // number of words if aligned uint32_t src = (uint32_t)k_src; uint32_t dst = (uint32_t)u_dst; if( (dst & 0x3) || (src & 0x3) ) wsize = 0; // not aligned else wsize = size >> 2; hal_disable_irq( &save_sr ); for( i = 0 ; i < wsize ; i++ ) // transfer one word per iteration { asm volatile( "mfc2 $15, $1 \n" /* save MMU_MODE */ "lw $13, 0(%0) \n" /* read data from kernel space */ "ori $14, $0, 0x7 \n" "mtc2 $14, $1 \n" /* MMU_MODE <= DTLB ON */ "sw $13, 0(%1) \n" /* store data to user space */ "mtc2 $15, $1 \n" /* restore MMU_MODE */ : : "r"( src ) , "r"( dst ) : "$13","$14","$15", "memory" ); src += 4; dst += 4; } for( i = wsize << 2 ; i < size ; i++ ) // transfer one byte per iteration { asm volatile( "mfc2 $15, $1 \n" /* save MMU_MODE */ "lw $13, 0(%0) \n" /* read data from kernel space */ "ori $14, $0, 0x7 \n" "mtc2 $14, $1 \n" /* MMU_MODE <= DTLB ON */ "sb $13, 0(%1) \n" /* store data to user space */ "mtc2 $15, $1 \n" /* restore MMU_MODE */ : : "r"( src ) , "r"( dst ) : "$13","$14","$15", "memory" ); src += 1; dst += 1; } hal_restore_irq( save_sr ); } // end hal_copy_to_uspace() ////////////////////////////////////////////// void hal_strcpy_from_uspace( char * k_dst, char * u_src, uint32_t size ) { uint32_t save_sr; uint32_t src = (uint32_t)u_src; uint32_t dst = (uint32_t)k_dst; hal_disable_irq( &save_sr ); // loop on characters while ( (character != NUL) and (count < size ) ) asm volatile( ".set noreorder \n" "move $11, %0 \n" /* $11 <= count == size */ "move $12, %1 \n" /* $12 <= u_src */ "move $13, %2 \n" /* $13 <= k_dst */ "mfc2 $15, $1 \n" /* $15 <= mode DTLB and ITLB off */ "ori $14, $15, 0x4 \n" /* $14 <= mode DTLB on */ "1: \n" "mtc2 $14, $1 \n" /* MMU_MODE <= DTLB ON */ "lb $10, 0($12) \n" /* read char from user space */ "mtc2 $15, $1 \n" /* restore DTLB and ITLB off */ "sb $10, 0($13) \n" /* store char to kernel space */ "beq $10, $0, 2f \n" /* exit if char = 0 */ "addi $11, $11, -1 \n" /* decrement count */ "addi $12, $12, 1 \n" /* increment u_src pointer */ "beq $11, $0, 2f \n" /* exit if count == 0 */ "addi $13, $13, 1 \n" /* increment k_src pointer */ "j 1b \n" /* jump to next iteration */ "2: \n" "nop \n" ".set reorder \n" : : "r"(size),"r"(src),"r"(dst) : "$10","$11","$12","$13","$14","$15" ); hal_restore_irq( save_sr ); } // hal_strcpy_from_uspace() //////////////////////////////////////////// void hal_strcpy_to_uspace( char * u_dst, char * k_src, uint32_t size ) { uint32_t save_sr; uint32_t src = (uint32_t)k_src; uint32_t dst = (uint32_t)u_dst; hal_disable_irq( &save_sr ); // loop on characters while ( (character != NUL) and (count < size) ) asm volatile( ".set noreorder \n" "move $11, %0 \n" /* $11 <= count == size */ "move $12, %1 \n" /* $12 <= k_src */ "move $13, %2 \n" /* $13 <= u_dst */ "mfc2 $15, $1 \n" /* $15 <= mode DTLB and ITLB off */ "ori $14, $15, 0x4 \n" /* $14 <= mode DTLB on */ "1: \n" "lb $10, 0($12) \n" /* read char from kernel space */ "mtc2 $14, $1 \n" /* MMU_MODE <= DTLB ON */ "sb $10, 0($13) \n" /* store char to user space */ "mtc2 $15, $1 \n" /* restore DTLB and ITLB off */ "beq $10, $0, 2f \n" /* exit if char == 0 */ "addi $11, $11, -1 \n" /* decrement count */ "addi $12, $12, 1 \n" /* increment k_src pointer */ "beq $11, $0, 2f \n" /* exit if count == size */ "addi $13, $13, 1 \n" /* increment u_src pointer */ "j 1b \n" /* jump to next iteration */ "2: \n" "nop \n" ".set reorder \n" : : "r"(size),"r"(src),"r"(dst) : "$10","$11","$12","$13","$14","$15" ); hal_restore_irq( save_sr ); } // hal_strcpy_to_uspace() /////////////////////////////////////////////// uint32_t hal_strlen_from_uspace( char * u_str ) { uint32_t save_sr; uint32_t count = 0; uint32_t str = (uint32_t)u_str; hal_disable_irq( &save_sr ); asm volatile( ".set noreorder \n" "move $13, %1 \n" /* $13 <= str */ "mfc2 $15, $1 \n" /* $15 <= DTLB and ITLB off */ "ori $14, $15, 0x4 \n" /* $14 <= mode DTLB on */ "1: \n" "mtc2 $14, $1 \n" /* set DTLB on */ "lb $12, 0($13) \n" /* read char from user space */ "mtc2 $15, $1 \n" /* set DTLB off */ "addi $13, $13, 1 \n" /* increment address */ "bne $12, $0, 1b \n" /* loop until NUL found */ "addi %0, %0, 1 \n" /* increment count */ ".set reorder \n" : "+r"(count) : "r"(str) : "$12","$13","$14","$15" ); hal_restore_irq( save_sr ); return count; }