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

Last change on this file since 632 was 626, checked in by alain, 5 years ago

This version has been tested on the sort multithreaded application
for TSAR_IOB architectures ranging from 1 to 8 clusters.
It fixes three bigs bugs:
1) the dev_ioc device API has been modified: the dev_ioc_sync_read()
and dev_ioc_sync_write() function use now extended pointers on the
kernel buffer to access a mapper stored in any cluster.
2) the hal_uspace API has been modified: the hal_copy_to_uspace()
and hal_copy_from_uspace() functions use now a (cxy,ptr) couple
to identify the target buffer (equivalent to an extended pointer.
3) an implementation bug has been fixed in the assembly code contained
in the hal_copy_to_uspace() and hal_copy_from_uspace() functions.

File size: 17.2 KB
RevLine 
[1]1/*
2 * hal_uspace.c - implementation of Generic User Space Access API for MIPS32
3 *
[626]4 * Author        Alain Greiner   (2016,2017,2018,2019)
[1]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
[457]24#include <hal_kernel_types.h>
[1]25#include <hal_uspace.h>
[626]26#include <hal_special.h>
[1]27#include <hal_irqmask.h>
28
[425]29#include <printk.h>
30#include <thread.h>
31
[626]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///////////////////////////////////////////////////////////////////////////////////////
48void hal_copy_from_uspace( cxy_t      k_cxy,
49                           void     * k_dst,
[1]50                           void     * u_src,
[425]51                           uint32_t   size ) 
[1]52{
53    uint32_t save_sr;
[626]54        uint32_t words;                        // number of words (if buffers aligned)
[1]55    uint32_t src = (uint32_t)u_src;
56    uint32_t dst = (uint32_t)k_dst;
[626]57 
[610]58#if DEBUG_HAL_USPACE
[626]59thread_t * this  = CURRENT_THREAD;
60uint32_t   cycle = (uint32_t)hal_get_cycles();
61if( cycle > DEBUG_HAL_USPACE )
62printk("\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 );
[610]64#endif
65
[626]66        if( (dst & 0x3) || (src & 0x3) ) words = 0;          // do it all in bytes
67    else                             words = size >> 2;
[1]68
[626]69    // enter critical section
[1]70    hal_disable_irq( &save_sr );
71
[626]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  */
[407]81
[626]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      */
[1]85
[626]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             */
[1]99
[626]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              */
[1]114
[626]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" );
[1]122
[626]123    // exit critical section
[1]124    hal_restore_irq( save_sr );
125
[610]126#if DEBUG_HAL_USPACE
[626]127cycle = (uint32_t)hal_get_cycles();
128if( cycle > DEBUG_HAL_USPACE )
129printk("\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 );
[610]131#endif
132
[87]133}  // end hal_copy_from_uspace()
134
[626]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///////////////////////////////////////////////////////////////////////////////////////
151void hal_copy_to_uspace( cxy_t      k_cxy,
[1]152                         void     * k_src,
[626]153                         void     * u_dst,
[1]154                         uint32_t   size )
155{
156    uint32_t save_sr;
[626]157        uint32_t words;                   // number of words (if buffers aligned)
[1]158    uint32_t src = (uint32_t)k_src;
159    uint32_t dst = (uint32_t)u_dst;
160
[610]161#if DEBUG_HAL_USPACE
[626]162thread_t * this  = CURRENT_THREAD;
163uint32_t   cycle = (uint32_t)hal_get_cycles();
164if( cycle > DEBUG_HAL_USPACE )
165printk("\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 );
[610]167#endif
168
[626]169        if( (dst & 0x3) || (src & 0x3) ) words = 0;          // not aligned
170    else                             words = size >> 2;
[1]171
[626]172    // enter critical section
[1]173    hal_disable_irq( &save_sr );
174
[626]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  */
[1]184
[626]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      */
[1]188
[626]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             */
[1]202
[626]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              */
[1]217
[626]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
[1]227    hal_restore_irq( save_sr );
228
[610]229#if DEBUG_HAL_USPACE
[626]230cycle = (uint32_t)hal_get_cycles();
231if( cycle > DEBUG_HAL_USPACE )
232printk("\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 );
[610]234#endif
235
[87]236}  // end hal_copy_to_uspace()
237
[407]238//////////////////////////////////////////////
239void hal_strcpy_from_uspace( char     * k_dst,
240                             char     * u_src,
241                             uint32_t   size )
[87]242{
[407]243    uint32_t save_sr;
[87]244    uint32_t src = (uint32_t)u_src;
245    uint32_t dst = (uint32_t)k_dst;
246
247    hal_disable_irq( &save_sr );
248
[425]249    // loop on characters while ( (character != NUL) and (count < size ) )
[87]250    asm volatile(
[407]251        ".set noreorder             \n"
252        "move   $11,   %0           \n"   /* $11 <= count == size           */
253        "move   $12,   %1           \n"   /* $12 <= u_src                   */
254        "move   $13,   %2           \n"   /* $13 <= k_dst                   */
[425]255        "mfc2   $15,   $1           \n"   /* $15 <= mode DTLB and ITLB off  */
256        "ori    $14,   $15,  0x4    \n"   /* $14 <= mode DTLB on            */
[407]257        "1:                         \n"
[87]258        "mtc2   $14,   $1                       \n"   /* MMU_MODE <= DTLB ON            */
[407]259        "lb     $10,   0($12)       \n"   /* read char from user space      */
[425]260        "mtc2   $15,   $1                       \n"   /* restore DTLB and ITLB off      */
[407]261            "sb     $10,   0($13)       \n"   /* store char to kernel space     */
[425]262        "beq    $10,   $0,   2f     \n"   /* exit if char = 0               */
[407]263        "addi   $11,   $11, -1      \n"   /* decrement count                */
264        "addi   $12,   $12,  1      \n"   /* increment u_src pointer        */
265        "beq    $11,   $0,   2f     \n"   /* exit if count == 0             */
266        "addi   $13,   $13,  1      \n"   /* increment k_src pointer        */
267        "j                   1b     \n"   /* jump to next iteration         */
268        "2:                         \n"
[87]269        "nop                        \n"
[407]270        ".set reorder               \n"
271        : 
272        : "r"(size),"r"(src),"r"(dst)
273        : "$10","$11","$12","$13","$14","$15" );
274       
275    hal_restore_irq( save_sr ); 
[87]276
277} // hal_strcpy_from_uspace()
278
[121]279////////////////////////////////////////////
[407]280void hal_strcpy_to_uspace( char     * u_dst,
281                           char     * k_src,
282                           uint32_t   size )
[121]283{
[407]284    uint32_t save_sr;
[87]285    uint32_t src = (uint32_t)k_src;
286    uint32_t dst = (uint32_t)u_dst;
287
288    hal_disable_irq( &save_sr );
289
[407]290    // loop on characters while ( (character != NUL) and (count < size) )
[87]291    asm volatile(
[407]292        ".set noreorder             \n"
293        "move   $11,   %0           \n"   /* $11 <= count == size           */
294        "move   $12,   %1           \n"   /* $12 <= k_src                   */
295        "move   $13,   %2           \n"   /* $13 <= u_dst                   */
[425]296        "mfc2   $15,   $1           \n"   /* $15 <= mode DTLB and ITLB off  */
297        "ori    $14,   $15,  0x4    \n"   /* $14 <= mode DTLB on            */
[407]298        "1:                         \n"
299        "lb     $10,   0($12)       \n"   /* read char from kernel space    */
[87]300        "mtc2   $14,   $1                       \n"   /* MMU_MODE <= DTLB ON            */
[407]301            "sb     $10,   0($13)       \n"   /* store char to user space       */
[425]302        "mtc2   $15,   $1                       \n"   /* restore DTLB and ITLB off      */
303        "beq    $10,   $0,   2f     \n"   /* exit if char == 0              */
[407]304        "addi   $11,   $11, -1      \n"   /* decrement count                */
305        "addi   $12,   $12,  1      \n"   /* increment k_src pointer        */
306        "beq    $11,   $0,   2f     \n"   /* exit if count == size          */
307        "addi   $13,   $13,  1      \n"   /* increment u_src pointer        */
308        "j                   1b     \n"   /* jump to next iteration         */
309        "2:                         \n"
[87]310        "nop                        \n"
[407]311        ".set reorder               \n"
312        :
313        : "r"(size),"r"(src),"r"(dst)
314        : "$10","$11","$12","$13","$14","$15" );
315       
316    hal_restore_irq( save_sr ); 
[87]317
[299]318} // hal_strcpy_to_uspace()
[87]319
[1]320///////////////////////////////////////////////
321uint32_t hal_strlen_from_uspace( char * u_str )
322{
323    uint32_t save_sr;
[407]324    uint32_t count = 0;
[425]325    uint32_t str   = (uint32_t)u_str;
[1]326
327    hal_disable_irq( &save_sr ); 
328
329        asm volatile(
[407]330        ".set noreorder             \n"
[425]331        "move   $13,   %1           \n"   /* $13 <= str                     */
[625]332        "mfc2   $15,   $1           \n"   /* $15 <= MMU_MODE (DTLB off)     */
[425]333        "ori    $14,   $15,  0x4    \n"   /* $14 <= mode DTLB on            */
[1]334        "1:                         \n"
[425]335        "mtc2   $14,   $1                       \n"   /* set DTLB on                    */
[625]336        "lb         $12,   0($13)       \n"   /* $12 <= one byte from u_space   */
[425]337        "mtc2   $15,   $1                       \n"   /* set DTLB off                   */
[1]338        "addi   $13,   $13,  1      \n"   /* increment address              */
[407]339        "bne    $12,   $0,   1b     \n"   /* loop until NUL found           */
340        "addi   %0,    %0,   1      \n"   /* increment count                */
341        ".set reorder               \n"
342        : "+r"(count) 
343        : "r"(str) 
344        : "$12","$13","$14","$15" );
[1]345
346    hal_restore_irq( save_sr );
347
348    return count;
349}
350
Note: See TracBrowser for help on using the repository browser.