Changeset 626 for trunk/hal/tsar_mips32/core
- Timestamp:
- Apr 29, 2019, 7:25:09 PM (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/hal/tsar_mips32/core/hal_uspace.c
r625 r626 2 2 * hal_uspace.c - implementation of Generic User Space Access API for MIPS32 3 3 * 4 * Author Mohamed Karaoui (2015) 5 * Alain Greiner (2016) 4 * Author Alain Greiner (2016,2017,2018,2019) 6 5 * 7 6 * Copyright (c) UPMC Sorbonne Universites … … 23 22 */ 24 23 25 #include <errno.h>26 #include <vmm.h>27 24 #include <hal_kernel_types.h> 28 25 #include <hal_uspace.h> 26 #include <hal_special.h> 29 27 #include <hal_irqmask.h> 30 28 … … 32 30 #include <thread.h> 33 31 34 /////////////////////////////////////////// 35 void hal_copy_from_uspace( void * k_dst, 32 /////////////////////////////////////////////////////////////////////////////////////// 33 // This function moves <size> bytes from a source buffer in user virtual space, 34 // defined by the <u_src> argument, to a destination kernel buffer, defined by the 35 // <k_cxy> and <k_dst> arguments. 36 // It works in a critical section, as it modifies briefly two CP2 registers: 37 // It activates briefly the DATA_MMU by writing into the CP2_MODE register to access the 38 // user buffer, and modifies the CP2_DATA_EXT register to access the kernel buffer. 39 // If the two buffers are aligned on a word boundary, it moves the data word per word 40 // in a first loop, and moves byte per byte the remaining bytes in a second loop. 41 // If the buffers are not aligned, it moves all data byte per byte. 42 /////////////////////////////////////////////////////////////////////////////////////// 43 // @ k_cxy : cluster of destination kernel buffer 44 // @ k_dst : pointer on destination kernel buffer 45 // @ u_src : pointer on source user buffer 46 // @ size : number of bytes to move 47 /////////////////////////////////////////////////////////////////////////////////////// 48 void hal_copy_from_uspace( cxy_t k_cxy, 49 void * k_dst, 36 50 void * u_src, 37 51 uint32_t size ) 38 52 { 39 53 uint32_t save_sr; 40 uint32_t i; 41 uint32_t wsize; // number of words 54 uint32_t words; // number of words (if buffers aligned) 42 55 uint32_t src = (uint32_t)u_src; 43 56 uint32_t dst = (uint32_t)k_dst; 44 57 45 58 #if DEBUG_HAL_USPACE 46 thread_t * this = CURRENT_THREAD; 47 printk("\n[%s] thread[%x,%x] enter in cluster %x / u_src %x / k_dst %x / size %d\n", 48 __FUNCTION__, this->process->pid, this->trdid, local_cxy, u_src, k_dst, size ); 59 thread_t * this = CURRENT_THREAD; 60 uint32_t cycle = (uint32_t)hal_get_cycles(); 61 if( cycle > DEBUG_HAL_USPACE ) 62 printk("\n[%s] thread[%x,%x] enter / %d bytes / u_buf(%x,%x) -> k_buf(%x,%x) / cycle %d\n", 63 __FUNCTION__, this->process->pid, this->trdid, size, local_cxy, u_src, k_cxy, k_dst, cycle ); 49 64 #endif 50 65 51 if( (dst & 0x3) || (src & 0x3) ) wsize = 0; // do it all in bytes 52 else wsize = size >> 2; 53 66 if( (dst & 0x3) || (src & 0x3) ) words = 0; // do it all in bytes 67 else words = size >> 2; 68 69 // enter critical section 54 70 hal_disable_irq( &save_sr ); 55 71 56 57 for( i = 0 ; i < wsize ; i++ ) // transfer one word per iteration 58 { 59 asm volatile( 60 "mfc2 $15, $1 \n" /* save MMU_MODE */ 61 "ori $14, $0, 0x7 \n" 62 "mtc2 $14, $1 \n" /* MMU_MODE <= DTLB ON */ 63 "lw $13, 0(%0) \n" /* read data from user space */ 64 "mtc2 $15, $1 \n" /* restore MMU_MODE */ 65 "sw $13, 0(%1) \n" /* store data to kernel space */ 66 : : "r"( src ) , "r"( dst ) : "$13","$14","$15", "memory" ); 67 68 src += 4; 69 dst += 4; 70 } 71 72 for( i = wsize << 2 ; i < size ; i++ ) // transfer one byte per iteration 73 { 74 asm volatile( 75 "mfc2 $15, $1 \n" /* save MMU_MODE */ 76 "ori $14, $0, 0x7 \n" 77 "mtc2 $14, $1 \n" /* MMU_MODE <= DTLB ON */ 78 "lb $13, 0(%0) \n" /* read data from user space */ 79 "mtc2 $15, $1 \n" /* restore MMU_MODE */ 80 "sb $13, 0(%1) \n" /* store data to kernel space */ 81 : : "r"( src ) , "r"( dst ) : "$13","$14","$15", "memory" ); 82 83 src += 1; 84 dst += 1; 85 } 86 72 asm volatile( ".set noreorder \n" 73 74 /* initialise registers */ 75 "move $8, %0 \n" /* $8 <= src */ 76 "move $9, %1 \n" /* $9 <= dst */ 77 "move $10, %2 \n" /* $10 <= words */ 78 "move $11, %3 \n" /* $11 <= size */ 79 "mfc2 $12, $1 \n" /* $12 <= old MMU_MODE */ 80 "ori $13, $12, 0x4 \n" /* $13 <= MMU_MODE with DTLB */ 81 82 /* save old MMU_DATA_EXT and set k_cxy in it */ 83 "mfc2 $16, $24 \n" /* $16 <= old MMU_DATA_EXT */ 84 "mtc2 %4, $24 \n" /* MMU_DATA_EXT <= k_cxy */ 85 86 /* transfer one word per iteration in first loop if aligned */ 87 "move $15, $10 \n" /* $15 <= words ($15 == i) */ 88 "1: \n" 89 "beq $15, $0, 2f \n" /* exit loop if (i==0) */ 90 "nop \n" 91 "mtc2 $13, $1 \n" /* MMU_MODE <= DTLB ON */ 92 "lw $14, 0($8) \n" /* word from user space */ 93 "mtc2 $12, $1 \n" /* restore old MMU_MODE */ 94 "sw $14, 0($9) \n" /* word to kernel space */ 95 "addi $15, $15, -1 \n" /* i-- */ 96 "addi $8, $8, 4 \n" /* src += 4 bytes */ 97 "j 1b \n" 98 "addi $9, $9, 4 \n" /* dst += 4 bytes */ 99 100 /* transfer one byte per iteration in this second loop */ 101 "2: \n" 102 "sll $15, $10, 2 \n" /* $15 <= words*4 ($15 == i) */ 103 "3: \n" 104 "beq $15, $11, 4f \n" /* exit loop if (i == size) */ 105 "nop \n" 106 "mtc2 $13, $1 \n" /* MMU_MODE <= DTLB ON */ 107 "lb $14, 0($8) \n" /* byte from user space */ 108 "mtc2 $12, $1 \n" /* restore omd MMU_MODE */ 109 "sb $14, 0($9) \n" /* byte to kernel space */ 110 "addi $15, $15, 1 \n" /* i++ */ 111 "addi $8, $8, 1 \n" /* src += 1 byte */ 112 "j 3b \n" 113 "addi $9, $9, 1 \n" /* dst += 1 byte */ 114 115 /* restore old MMU_DATA_EXT register */ 116 "4: \n" 117 "mtc2 $16, $24 \n" /* MMU__DATA_EXT <= $16 */ 118 ".set reorder \n" 119 : 120 : "r"(src) , "r"(dst) , "r"(words) , "r"(size) , "r"(k_cxy) 121 : "$8","$9","$10","$11","$12","$13","$14","$15","$16","memory" ); 122 123 // exit critical section 87 124 hal_restore_irq( save_sr ); 88 125 89 126 #if DEBUG_HAL_USPACE 90 printk("\n[%s] thread[%x,%x] exit\n", 91 __FUNCTION__, this->process->pid, this->trdid ); 127 cycle = (uint32_t)hal_get_cycles(); 128 if( cycle > DEBUG_HAL_USPACE ) 129 printk("\n[%s] thread[%x,%x] moved %d bytes / u_buf(%x,%x) -> k_buf(%x,%x) / cycle %d\n", 130 __FUNCTION__, this->process->pid, this->trdid, size, local_cxy, u_src, k_cxy, k_dst, cycle ); 92 131 #endif 93 132 94 133 } // end hal_copy_from_uspace() 95 134 96 /////////////////////////////////////////// 97 void hal_copy_to_uspace( void * u_dst, 135 /////////////////////////////////////////////////////////////////////////////////////// 136 // This function moves <size> bytes from a source kernel buffer, defined by the 137 // <k_cxy> and <k_src> arguments, to a destination buffer in user virtual space, 138 // defined by the <u_dst> argument. 139 // It works in a critical section, as it modifies briefly two CP2 registers: 140 // It activates briefly the DATA_MMU by writing into the CP2_MODE register to access the 141 // user buffer, and modifies the CP2_DATA_EXT register to access the kernel buffer. 142 // If the two buffers are aligned on a word boundary, it moves the data word per word 143 // in a first loop, and moves byte per byte the remaining bytes in a second loop. 144 // If the buffers are not aligned, it moves all data byte per byte. 145 /////////////////////////////////////////////////////////////////////////////////////// 146 // @ k_cxy : cluster of destination kernel buffer 147 // @ k_dst : pointer on destination kernel buffer 148 // @ u_src : pointer on source user buffer 149 // @ size : number of bytes to move 150 /////////////////////////////////////////////////////////////////////////////////////// 151 void hal_copy_to_uspace( cxy_t k_cxy, 98 152 void * k_src, 153 void * u_dst, 99 154 uint32_t size ) 100 155 { 101 156 uint32_t save_sr; 102 uint32_t i; 103 uint32_t wsize; // number of words if aligned 157 uint32_t words; // number of words (if buffers aligned) 104 158 uint32_t src = (uint32_t)k_src; 105 159 uint32_t dst = (uint32_t)u_dst; 106 160 107 161 #if DEBUG_HAL_USPACE 108 thread_t * this = CURRENT_THREAD; 109 printk("\n[%s] thread[%x,%x] enter in cluster %x / k_src %x / u_dst %x / size %d\n", 110 __FUNCTION__, this->process->pid, this->trdid, local_cxy, k_src, u_dst, size ); 162 thread_t * this = CURRENT_THREAD; 163 uint32_t cycle = (uint32_t)hal_get_cycles(); 164 if( cycle > DEBUG_HAL_USPACE ) 165 printk("\n[%s] thread[%x,%x] enter / %d bytes / k_buf(%x,%x) -> u_buf(%x,%x) / cycle %d\n", 166 __FUNCTION__, this->process->pid, this->trdid, size, k_cxy, k_src, local_cxy, u_dst, cycle ); 111 167 #endif 112 168 113 if( (dst & 0x3) || (src & 0x3) ) wsize = 0; // not aligned 114 else wsize = size >> 2; 115 169 if( (dst & 0x3) || (src & 0x3) ) words = 0; // not aligned 170 else words = size >> 2; 171 172 // enter critical section 116 173 hal_disable_irq( &save_sr ); 117 174 118 for( i = 0 ; i < wsize ; i++ ) // transfer one word per iteration 119 { 120 asm volatile( 121 "mfc2 $15, $1 \n" /* save MMU_MODE */ 122 "lw $13, 0(%0) \n" /* read data from kernel space */ 123 "ori $14, $0, 0x7 \n" 124 "mtc2 $14, $1 \n" /* MMU_MODE <= DTLB ON */ 125 "sw $13, 0(%1) \n" /* store data to user space */ 126 "mtc2 $15, $1 \n" /* restore MMU_MODE */ 127 : : "r"( src ) , "r"( dst ) : "$13","$14","$15", "memory" ); 128 129 src += 4; 130 dst += 4; 131 } 132 133 for( i = wsize << 2 ; i < size ; i++ ) // transfer one byte per iteration 134 { 135 asm volatile( 136 "mfc2 $15, $1 \n" /* save MMU_MODE */ 137 "lb $13, 0(%0) \n" /* read data from kernel space */ 138 "ori $14, $0, 0x7 \n" 139 "mtc2 $14, $1 \n" /* MMU_MODE <= DTLB ON */ 140 "sb $13, 0(%1) \n" /* store data to user space */ 141 "mtc2 $15, $1 \n" /* restore MMU_MODE */ 142 : : "r"( src ) , "r"( dst ) : "$13","$14","$15", "memory" ); 143 144 src += 1; 145 dst += 1; 146 } 147 175 asm volatile( ".set noreorder \n" 176 177 /* initialise registers */ 178 "move $8, %0 \n" /* $8 <= k_src */ 179 "move $9, %1 \n" /* $9 <= u_dst */ 180 "move $10, %2 \n" /* $10 <= words */ 181 "move $11, %3 \n" /* $11 <= size */ 182 "mfc2 $12, $1 \n" /* $12 <= old MMU_MODE */ 183 "ori $13, $12, 0x4 \n" /* $13 <= MMU_MODE with DTLB */ 184 185 /* save old MMU_DATA_EXT and set k_cxy in it */ 186 "mfc2 $16, $24 \n" /* $16 <= old MMU_DATA_EXT */ 187 "mtc2 %4, $24 \n" /* MMU_DATA_EXT <= k_cxy */ 188 189 /* transfer one word per iteration in first loop if aligned */ 190 "move $15, $10 \n" /* $15 <= words ($15 == i) */ 191 "1: \n" 192 "beq $15, $0, 2f \n" /* exit loop if (i==0) */ 193 "nop \n" 194 "lw $14, 0($8) \n" /* load from kernel space */ 195 "mtc2 $13, $1 \n" /* MMU_MODE <= DTLB ON */ 196 "sw $14, 0($9) \n" /* store to user space */ 197 "mtc2 $12, $1 \n" /* restore old MMU_MODE */ 198 "addi $15, $15, -1 \n" /* i-- */ 199 "addi $8, $8, 4 \n" /* src += 4 bytes */ 200 "j 1b \n" 201 "addi $9, $9, 4 \n" /* dst += 4 bytes */ 202 203 /* transfer one byte per iteration in this second loop */ 204 "2: \n" 205 "sll $15, $10, 2 \n" /* $15 <= words*4 ($15 == i) */ 206 "3: \n" 207 "beq $15, $11, 4f \n" /* exit loop if (i == size) */ 208 "nop \n" 209 "lb $14, 0($8) \n" /* byte from kernel space */ 210 "mtc2 $13, $1 \n" /* MMU_MODE <= DTLB ON */ 211 "sb $14, 0($9) \n" /* byte to user space */ 212 "mtc2 $12, $1 \n" /* restore omd MMU_MODE */ 213 "addi $15, $15, 1 \n" /* i++ */ 214 "addi $8, $8, 1 \n" /* src += 1 byte */ 215 "j 3b \n" 216 "addi $9, $9, 1 \n" /* dst += 1 byte */ 217 218 /* restore old MMU_DATA_EXT register */ 219 "4: \n" 220 "mtc2 $16, $24 \n" /* MMU__DATA_EXT <= $16 */ 221 ".set reorder \n" 222 : 223 : "r"(src) , "r"(dst) , "r"(words) , "r"(size) , "r"(k_cxy) 224 : "$8","$9","$10","$11","$12","$13","$14","$15","$16","memory" ); 225 226 // exit critical section 148 227 hal_restore_irq( save_sr ); 149 228 150 229 #if DEBUG_HAL_USPACE 151 printk("\n[%s] thread[%x,%x] exit\n", 152 __FUNCTION__, this->process->pid, this->trdid ); 230 cycle = (uint32_t)hal_get_cycles(); 231 if( cycle > DEBUG_HAL_USPACE ) 232 printk("\n[%s] thread[%x,%x] moved %d bytes / k_buf(%x,%x) -> u_buf(%x,%x) / cycle %d\n", 233 __FUNCTION__, this->process->pid, this->trdid, size, k_cxy, k_src, local_cxy, u_dst, cycle ); 153 234 #endif 154 235
Note: See TracChangeset
for help on using the changeset viewer.