source: trunk/hal/tsar_mips32/core/hal_uspace.c @ 657

Last change on this file since 657 was 657, checked in by alain, 4 years ago

Introduce remote_buf.c/.h & socket.c/.h files.
Update dev_nic.c/.h files.

File size: 18.2 KB
Line 
1/*
2 * hal_uspace.c - implementation of Generic User Space Access API for MIPS32
3 *
4 * Author        Alain Greiner   (2016,2017,2018,2019,2020)
5 *
6 * Copyright (c) UPMC Sorbonne Universites
7 *
8 * This file is part of ALMOS-MKH..
9 *
10 * ALMOS-MKH. is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; version 2.0 of the License.
13 *
14 * ALMOS-MKH. is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with ALMOS-MKH.; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24#include <hal_kernel_types.h>
25#include <hal_uspace.h>
26#include <hal_special.h>
27#include <hal_irqmask.h>
28
29#include <printk.h>
30#include <thread.h>
31
32///////////////////////////////////////////////////////////////////////////////////////
33// This function moves <size> bytes from a source buffer in user virtual space,
34// defined by the <u_src_ptr> argument, to a destination kernel buffer, defined by the
35// <k_dst_xp> argument.
36// It works in a critical section, as it modifies 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_DEXT 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_dst_xp  : extended pointer on destination kernel buffer
44// @ u_src_ptr : pointer on source user buffer
45// @ size     : number of bytes to move
46///////////////////////////////////////////////////////////////////////////////////////
47void hal_copy_from_uspace( xptr_t     k_dst_xp,
48                           void     * u_src_ptr,
49                           uint32_t   size ) 
50{
51    uint32_t save_sr;
52        uint32_t words;                            // number of words (if buffers aligned)
53    uint32_t src = (uint32_t)u_src_ptr;
54    uint32_t dst = (uint32_t)GET_PTR( k_dst_xp );
55    uint32_t cxy = (uint32_t)GET_CXY( k_dst_xp );
56 
57#if DEBUG_HAL_USPACE
58thread_t * this  = CURRENT_THREAD;
59uint32_t   cycle = (uint32_t)hal_get_cycles();
60if( cycle > DEBUG_HAL_USPACE )
61printk("\n[%s] thread[%x,%x] enter / %d bytes / u_buf(%x,%x) -> k_buf(%x,%x) / cycle %d\n", 
62__FUNCTION__, this->process->pid, this->trdid, size, local_cxy, src, cxy, dst, cycle );
63#endif
64
65        if( (dst & 0x3) || (src & 0x3) ) words = 0;          // do it all in bytes
66    else                             words = size >> 2;
67
68    // enter critical section
69    hal_disable_irq( &save_sr );
70
71    asm volatile( ".set noreorder             \n"
72 
73                  /* initialise registers                                         */
74                  "move   $8,    %0           \n"   /* $8 <= src                  */
75                  "move   $9,    %1           \n"   /* $9 <= dst                  */
76                  "move   $10,   %2           \n"   /* $10 <= words               */
77                  "move   $11,   %3           \n"   /* $11 <= size                */
78                  "mfc2   $12,   $1           \n"   /* $12 <= old MMU_MODE        */
79                  "ori    $13,   $12,   0x4       \n"   /* $13 <= MMU_MODE with DTLB  */
80
81                  /* save MMU_DEXT register                                       */
82                  "mfc2   $16,   $24          \n"   /* $16 <= old MMU_DEXT        */
83                  "mtc2   %4,    $24          \n"   /* MMU_DEXT <= dst_cxy        */
84
85                  /* transfer one word per iteration in first loop if aligned     */
86                  "move   $15,   $10          \n"   /* $15 <= words ($15 == i)    */
87                  "1:                         \n"
88                  "beq    $15,   $0,    2f    \n"   /* exit loop if (i==0)        */
89                  "nop                        \n"
90                  "mtc2   $13,   $1                       \n"   /* MMU_MODE <= DTLB ON        */
91                  "lw     $14,   0($8)        \n"   /* word from user space       */
92                  "mtc2   $12,   $1                       \n"   /* restore old MMU_MODE       */
93                      "sw     $14,   0($9)        \n"   /* word to kernel space       */
94                  "addi   $15,   $15,   -1    \n"   /* i--                        */
95                  "addi   $8,    $8,    4     \n"   /* src += 4 bytes             */
96                  "j             1b           \n"   
97                  "addi   $9,    $9,    4     \n"   /* dst += 4 bytes             */
98
99                  /* transfer one byte per iteration in this second loop          */
100                  "2:                         \n"
101                  "sll    $15,   $10,   2     \n"   /* $15 <= words*4 ($15 == i)  */
102                  "3:                         \n"
103                  "beq    $15,   $11,   4f    \n"   /* exit loop if (i == size)   */
104                  "nop                        \n"
105                  "mtc2   $13,   $1                       \n"   /* MMU_MODE <= DTLB ON        */
106                  "lb     $14,   0($8)        \n"   /* byte from user space       */
107                  "mtc2   $12,   $1                       \n"   /* restore omd MMU_MODE       */
108                      "sb     $14,   0($9)        \n"   /* byte to kernel space       */
109                  "addi   $15,   $15,   1     \n"   /* i++                        */
110                  "addi   $8,    $8,    1     \n"   /* src += 1 byte              */
111                  "j             3b           \n"   
112                  "addi   $9,    $9,    1     \n"   /* dst += 1 byte              */
113
114                  /* restore MMU_DEXT register                                    */
115                  "4:                         \n"
116                  "mtc2   $16,   $24          \n"   /* MMU_DEXT <= $16            */
117                  ".set reorder               \n"
118                  : 
119                  : "r"(src) , "r"(dst) , "r"(words) , "r"(size) , "r"(cxy)
120                  : "$8","$9","$10","$11","$12","$13","$14","$15","$16","memory" );
121
122    // exit critical section
123    hal_restore_irq( save_sr );
124
125#if DEBUG_HAL_USPACE
126cycle = (uint32_t)hal_get_cycles();
127if( cycle > DEBUG_HAL_USPACE )
128printk("\n[%s] thread[%x,%x] moved %d bytes / u_buf(%x,%x) -> k_buf(%x,%x) / cycle %d\n", 
129__FUNCTION__, this->process->pid, this->trdid, size, local_cxy, src, cxy, dst, cycle );
130#endif
131
132}  // end hal_copy_from_uspace()
133
134///////////////////////////////////////////////////////////////////////////////////////
135// This function moves <size> bytes from a source kernel buffer, defined by the
136// <k_src_xp> argument, to a destination buffer in user virtual space, defined by
137// the <u_dst_ptr> argument.
138// It works in a critical section, as it modifies two CP2 registers:
139// It activates briefly the DATA_MMU by writing into the CP2_MODE register to access the
140// user buffer, and modifies the CP2_DEXT register to access the kernel buffer.
141// If the two buffers are aligned on a word boundary, it moves the data word per word
142// in a first loop, and moves byte per byte the remaining bytes in a second loop.
143// If the buffers are not word aligned, it moves all data byte per byte.
144///////////////////////////////////////////////////////////////////////////////////////
145// @ u_dst_ptr : pointer on destination user buffer
146// @ k_src_xp  : extended pointer on source kernel buffer
147// @ size      : number of bytes to move
148///////////////////////////////////////////////////////////////////////////////////////
149void hal_copy_to_uspace( void     * u_dst_ptr,
150                         xptr_t     k_src_xp,
151                         uint32_t   size )
152{
153    uint32_t save_sr;
154        uint32_t words;                           // number of words (if buffers aligned)
155    uint32_t dst = (uint32_t)u_dst_ptr;
156    uint32_t src = (uint32_t)GET_PTR( k_src_xp );
157    uint32_t cxy = (uint32_t)GET_CXY( k_src_xp );
158
159#if DEBUG_HAL_USPACE
160thread_t * this  = CURRENT_THREAD;
161uint32_t   cycle = (uint32_t)hal_get_cycles();
162if( cycle > DEBUG_HAL_USPACE )
163printk("\n[%s] thread[%x,%x] enter / %d bytes / k_buf(%x,%x) -> u_buf(%x,%x) / cycle %d\n", 
164__FUNCTION__, this->process->pid, this->trdid, size, cxy, src, local_cxy, dst, cycle );
165#endif
166
167        if( (dst & 0x3) || (src & 0x3) ) words = 0;          // not aligned
168    else                             words = size >> 2;
169
170    // enter critical section
171    hal_disable_irq( &save_sr );
172
173    asm volatile( ".set noreorder             \n"
174 
175                  /* initialise registers                                         */
176                  "move   $8,    %0           \n"   /* $8 <= k_src                */
177                  "move   $9,    %1           \n"   /* $9 <= u_dst                */
178                  "move   $10,   %2           \n"   /* $10 <= words               */
179                  "move   $11,   %3           \n"   /* $11 <= size                */
180                  "mfc2   $12,   $1           \n"   /* $12 <= old MMU_MODE        */
181                  "ori    $13,   $12,   0x4       \n"   /* $13 <= MMU_MODE with DTLB  */
182
183                  /* save MMU_DEXT register                                       */
184                  "mfc2   $16,   $24          \n"   /* $16 <= old MMU_DEXT        */
185                  "mtc2   %4,    $24          \n"   /* MMU_DEXT <= cxy            */
186
187                  /* transfer one word per iteration in first loop if aligned     */
188                  "move   $15,   $10          \n"   /* $15 <= words ($15 == i)    */
189                  "1:                         \n"
190                  "beq    $15,   $0,    2f    \n"   /* exit loop if (i==0)        */
191                  "nop                        \n"
192                  "lw     $14,   0($8)        \n"   /* load from kernel space     */
193                  "mtc2   $13,   $1                       \n"   /* MMU_MODE <= DTLB ON        */
194                      "sw     $14,   0($9)        \n"   /* store to user space        */
195                  "mtc2   $12,   $1                       \n"   /* restore old MMU_MODE       */
196                  "addi   $15,   $15,   -1    \n"   /* i--                        */
197                  "addi   $8,    $8,    4     \n"   /* src += 4 bytes             */
198                  "j             1b           \n"   
199                  "addi   $9,    $9,    4     \n"   /* dst += 4 bytes             */
200
201                  /* transfer one byte per iteration in this second loop          */
202                  "2:                         \n"
203                  "sll    $15,   $10,   2     \n"   /* $15 <= words*4 ($15 == i)  */
204                  "3:                         \n"
205                  "beq    $15,   $11,   4f    \n"   /* exit loop if (i == size)   */
206                  "nop                        \n"
207                  "lb     $14,   0($8)        \n"   /* byte from kernel space     */
208                  "mtc2   $13,   $1                       \n"   /* MMU_MODE <= DTLB ON        */
209                      "sb     $14,   0($9)        \n"   /* byte to user space         */
210                  "mtc2   $12,   $1                       \n"   /* restore omd MMU_MODE       */
211                  "addi   $15,   $15,   1     \n"   /* i++                        */
212                  "addi   $8,    $8,    1     \n"   /* src += 1 byte              */
213                  "j             3b           \n"   
214                  "addi   $9,    $9,    1     \n"   /* dst += 1 byte              */
215
216                  /* restore MMU_DEXT register                                    */
217                  "4:                         \n"
218                  "mtc2   $16,   $24          \n"   /* MMU_DEXT <= $16            */
219                  ".set reorder               \n"
220                  : 
221                  : "r"(src) , "r"(dst) , "r"(words) , "r"(size) , "r"(cxy)
222                  : "$8","$9","$10","$11","$12","$13","$14","$15","$16","memory" );
223
224    // exit critical section
225    hal_restore_irq( save_sr );
226
227#if DEBUG_HAL_USPACE
228cycle = (uint32_t)hal_get_cycles();
229if( cycle > DEBUG_HAL_USPACE )
230printk("\n[%s] thread[%x,%x] moved %d bytes / k_buf(%x,%x) -> u_buf(%x,%x) / cycle %d\n", 
231__FUNCTION__, this->process->pid, this->trdid, size, cxy, src, local_cxy, dst, cycle );
232#endif
233
234}  // end hal_copy_to_uspace()
235
236/////////////////////////////////////////////////
237void hal_strcpy_from_uspace( xptr_t     k_dst_xp,
238                             char     * u_src_ptr,
239                             uint32_t   size )
240{
241    uint32_t save_sr;
242    uint32_t src = (uint32_t)u_src_ptr;
243    uint32_t dst = (uint32_t)GET_PTR( k_dst_xp );
244    uint32_t cxy = (uint32_t)GET_CXY( k_dst_xp );
245
246    hal_disable_irq( &save_sr );
247
248    // loop on characters while ( (character != NUL) and (count < size ) )
249
250    asm volatile(
251        ".set noreorder             \n"
252
253        /* save old MMU_DEXT and set cxy in it                              */
254        "mfc2   $16,   $24          \n"   /* $16 <= old MMU_DEXT            */
255        "mtc2   %3,    $24          \n"   /* MMU_DEXT <= cxy                */
256
257        "move   $11,   %0           \n"   /* $11 <= count == size           */
258        "move   $12,   %1           \n"   /* $12 <= u_src                   */
259        "move   $13,   %2           \n"   /* $13 <= k_dst                   */
260        "mfc2   $15,   $1           \n"   /* $15 <= MMU_MODE                */
261        "ori    $14,   $15,  0x4    \n"   /* $14 <= MMU_MODE / DTLB ON      */
262
263        "1:                         \n"
264        "mtc2   $14,   $1                       \n"   /* MMU_MODE <= DTLB ON            */
265        "lb     $10,   0($12)       \n"   /* read char from user space      */
266        "mtc2   $15,   $1                       \n"   /* MMU_MODE <= DTLB OFF           */
267            "sb     $10,   0($13)       \n"   /* store char to kernel space     */
268        "beq    $10,   $0,   2f     \n"   /* exit if char = 0               */
269        "addi   $11,   $11, -1      \n"   /* decrement count                */
270        "addi   $12,   $12,  1      \n"   /* increment u_src pointer        */
271        "beq    $11,   $0,   2f     \n"   /* exit if count == 0             */
272        "addi   $13,   $13,  1      \n"   /* increment k_src pointer        */
273        "j                   1b     \n"   /* jump to next iteration         */
274        "2:                         \n"
275        "nop                        \n"
276
277        /* restore old MMU_DEXT register                                    */
278        "mtc2   $16,   $24          \n"   /* MMU_DEXT <= $16                */
279
280        ".set reorder               \n"
281        : 
282        : "r"(size) , "r"(src) , "r"(dst) , "r"(cxy)
283        : "$10","$11","$12","$13","$14","$15","$16" );
284       
285    hal_restore_irq( save_sr ); 
286
287} // hal_strcpy_from_uspace()
288
289////////////////////////////////////////////////
290void hal_strcpy_to_uspace( char     * u_dst_ptr,
291                           xptr_t     k_src_xp,
292                           uint32_t   size )
293{
294    uint32_t save_sr;
295    uint32_t dst = (uint32_t)u_dst_ptr;
296    uint32_t src = (uint32_t)GET_PTR( k_src_xp );
297    uint32_t cxy = (uint32_t)GET_CXY( k_src_xp );
298
299    hal_disable_irq( &save_sr );
300
301    // loop on characters while ( (character != NUL) and (count < size) )
302
303    asm volatile(
304        ".set noreorder             \n"
305
306        /* save old MMU_DEXT and set cxy in it                              */
307        "mfc2   $16,   $24          \n"   /* $16 <= old MMU_DEXT            */
308        "mtc2   %3,    $24          \n"   /* MMU_DEXT <= cxy                */
309
310        "move   $11,   %0           \n"   /* $11 <= count == size           */
311        "move   $12,   %1           \n"   /* $12 <= k_src                   */
312        "move   $13,   %2           \n"   /* $13 <= u_dst                   */
313        "mfc2   $15,   $1           \n"   /* $15 <= MMU_MODE                */
314        "ori    $14,   $15,  0x4    \n"   /* $14 <= MMU_MODE modified       */
315
316        "1:                         \n"
317        "lb     $10,   0($12)       \n"   /* read char from kernel space    */
318        "mtc2   $14,   $1                       \n"   /* MMU_MODE <= DTLB ON            */
319            "sb     $10,   0($13)       \n"   /* store char to user space       */
320        "mtc2   $15,   $1                       \n"   /* MMU_MODE <= DTLB OFF           */
321        "beq    $10,   $0,   2f     \n"   /* exit if char == 0              */
322        "addi   $11,   $11, -1      \n"   /* decrement count                */
323        "addi   $12,   $12,  1      \n"   /* increment k_src pointer        */
324        "beq    $11,   $0,   2f     \n"   /* exit if count == 0             */
325        "addi   $13,   $13,  1      \n"   /* increment u_src pointer        */
326        "j                   1b     \n"   /* jump to next iteration         */
327        "2:                         \n"
328        "nop                        \n"
329
330        /* restore old MMU_DEXT register                                    */
331        "mtc2   $16,   $24          \n"   /* MMU_DEXT <= $16                */
332
333        ".set reorder               \n"
334        :
335        : "r"(size) , "r"(src) , "r"(dst) , "r"(cxy)
336        : "$10","$11","$12","$13","$14","$15","$16" );
337       
338    hal_restore_irq( save_sr ); 
339
340} // hal_strcpy_to_uspace()
341
342///////////////////////////////////////////////
343uint32_t hal_strlen_from_uspace( char * u_str )
344{
345    uint32_t save_sr;
346    uint32_t count = 0;
347    uint32_t str   = (uint32_t)u_str;
348
349    hal_disable_irq( &save_sr ); 
350
351        asm volatile(
352        ".set noreorder             \n"
353        "move   $13,   %1           \n"   /* $13 <= str                     */
354        "mfc2   $15,   $1           \n"   /* $15 <= MMU_MODE (DTLB off)     */
355        "ori    $14,   $15,  0x4    \n"   /* $14 <= mode DTLB on            */
356        "1:                         \n"
357        "mtc2   $14,   $1                       \n"   /* set DTLB on                    */
358        "lb         $12,   0($13)       \n"   /* $12 <= one byte from u_space   */
359        "mtc2   $15,   $1                       \n"   /* set DTLB off                   */
360        "addi   $13,   $13,  1      \n"   /* increment address              */
361        "bne    $12,   $0,   1b     \n"   /* loop until NUL found           */
362        "addi   %0,    %0,   1      \n"   /* increment count                */
363        ".set reorder               \n"
364        : "+r"(count) 
365        : "r"(str) 
366        : "$12","$13","$14","$15" );
367
368    hal_restore_irq( save_sr );
369
370    return count;
371}
372
Note: See TracBrowser for help on using the repository browser.