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

Last change on this file since 300 was 300, checked in by max@…, 5 years ago

Passably handle everything in the function itself.

File size: 8.7 KB
Line 
1/*
2 * hal_uspace.c - implementation of Generic User Space Access API for MIPS32
3 *
4 * Author  Mohamed Karaoui (2015)
5 *         Alain Greiner   (2016)
6 *
7 * Copyright (c) UPMC Sorbonne Universites
8 *
9 * This file is part of ALMOS-MKH..
10 *
11 * ALMOS-MKH. is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; version 2.0 of the License.
14 *
15 * ALMOS-MKH. is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with ALMOS-MKH.; if not, write to the Free Software Foundation,
22 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25#include <hal_types.h>
26#include <hal_uspace.h>
27#include <hal_irqmask.h>
28
29///////////////////////////////////////////
30void hal_copy_from_uspace( void     * k_dst,
31                           void     * u_src,
32                           uint32_t   size )
33{
34    uint32_t save_sr;
35        uint32_t i;
36        uint32_t wsize;                        // number of words
37    uint32_t src = (uint32_t)u_src;
38    uint32_t dst = (uint32_t)k_dst;
39
40        if( (dst & 0x3) || (src & 0x3) ) wsize = 0;          // do it all in bytes
41    else                             wsize = size >> 2;
42
43    hal_disable_irq( &save_sr );
44
45        for( i = 0 ; i < wsize ; i++ )          // transfer one word per iteration
46        {
47        asm volatile(
48        "mfc2   $15,   $1           \n"   /* save   MMU_MODE                */
49        "ori    $14,   $0,  0x7     \n" 
50        "mtc2   $14,   $1                       \n"   /* MMU_MODE <= DTLB ON            */
51        "lw         $13,   0(%0)        \n"   /* read data from user space      */
52        "mtc2   $15,   $1                       \n"   /* restore MMU_MODE               */
53            "sw     $13,   0(%1)        \n"   /* store data to kernel space     */
54        : : "r"( src ) , "r"( dst ) : "$13","$14","$15", "memory" );
55
56        src += 4;
57        dst += 4;
58    }
59
60        for( i = wsize << 2 ; i < size ; i++ )  // transfer one byte per iteration
61        {
62        asm volatile(
63        "mfc2   $15,   $1           \n"   /* save   MMU_MODE                */
64        "ori    $14,   $0,  0x7     \n" 
65        "mtc2   $14,   $1                       \n"   /* MMU_MODE <= DTLB ON            */
66        "lb         $13,   0(%0)        \n"   /* read data from user space      */
67        "mtc2   $15,   $1                       \n"   /* restore MMU_MODE               */
68            "sb     $13,   0(%1)        \n"   /* store data to kernel space     */
69        : : "r"( src ) , "r"( dst ) : "$13","$14","$15", "memory" );
70
71        src += 1;
72        dst += 1;
73    }
74
75    hal_restore_irq( save_sr );
76
77}  // end hal_copy_from_uspace()
78
79///////////////////////////////////////////
80void hal_copy_to_uspace( void     * u_dst,
81                         void     * k_src,
82                         uint32_t   size )
83{
84    uint32_t save_sr;
85        uint32_t i;
86        uint32_t wsize;                   // number of words if aligned
87    uint32_t src = (uint32_t)k_src;
88    uint32_t dst = (uint32_t)u_dst;
89
90        if( (dst & 0x3) || (src & 0x3) ) wsize = 0;          // not aligned
91    else                             wsize = size >> 2;
92
93    hal_disable_irq( &save_sr );
94
95        for( i = 0 ; i < wsize ; i++ )          // transfer one word per iteration
96        {
97        asm volatile(
98        "mfc2   $15,   $1           \n"   /* save   MMU_MODE                */
99        "lw         $13,   0(%0)        \n"   /* read data from kernel space    */
100        "ori    $14,   $0,  0x7     \n" 
101        "mtc2   $14,   $1                       \n"   /* MMU_MODE <= DTLB ON            */
102            "sw     $13,   0(%1)        \n"   /* store data to user space       */
103        "mtc2   $15,   $1                       \n"   /* restore MMU_MODE               */
104        : : "r"( src ) , "r"( dst ) : "$13","$14","$15", "memory" );
105
106        src += 4;
107        dst += 4;
108    }
109
110        for( i = wsize << 2 ; i < size ; i++ )  // transfer one byte per iteration
111        {
112        asm volatile(
113        "mfc2   $15,   $1           \n"   /* save   MMU_MODE                */
114        "lw         $13,   0(%0)        \n"   /* read data from kernel space    */
115        "ori    $14,   $0,  0x7     \n" 
116        "mtc2   $14,   $1                       \n"   /* MMU_MODE <= DTLB ON            */
117            "sb     $13,   0(%1)        \n"   /* store data to user space       */
118        "mtc2   $15,   $1                       \n"   /* restore MMU_MODE               */
119        : : "r"( src ) , "r"( dst ) : "$13","$14","$15", "memory" );
120
121        src += 1;
122        dst += 1;
123    }
124
125    hal_restore_irq( save_sr );
126
127}  // end hal_copy_to_uspace()
128
129//////////////////////////////////////////
130error_t hal_strcpy_from_uspace( char     * k_dst,
131                                char     * u_src,
132                                uint32_t   max_size )
133
134{
135
136// TODO implement the max_size handling, and error handling
137
138    uint32_t save_sr;
139    uint32_t src = (uint32_t)u_src;
140    uint32_t dst = (uint32_t)k_dst;
141    uint32_t length;
142    error_t error;
143    paddr_t paddr;
144
145    // XXX XXX XXX: must be converted, to handle faults
146    error = vmm_v2p_translate( false , u_src , &paddr );
147    if( error )
148    {
149        return EFAULT;
150    }
151    length = hal_strlen_from_uspace( u_src );
152    if( length >= max_size )
153    {
154        return EFAULT;
155    }
156
157    hal_disable_irq( &save_sr );
158
159    // loop on characters while non NUL
160    asm volatile(
161        "mfc2   $15,   $1           \n"   /* save current MMU_MODE          */
162        "1:                         \n"   /* loop entry                     */
163        "ori    $14,   $0,  0x7     \n" 
164        "mtc2   $14,   $1                       \n"   /* MMU_MODE <= DTLB ON            */
165        "lb         $13,   0(%0)        \n"   /* read char from user space      */
166        "mtc2   $15,   $1                       \n"   /* restore MMU_MODE               */
167            "sb     $13,   0(%1)        \n"   /* store char to kernel space     */
168        "addi   %0,    %0,  1       \n"   /* increment SRC pointer          */
169        "addi   %1,    %1,  1       \n"   /* increment DST pointer          */
170        "bne    $13,   $0,  1b      \n"   /* test NUL                       */
171        "nop                        \n"
172        : : "r"( src ) , "r"( dst ) : "$13","$14","$15", "memory" );
173
174    hal_restore_irq( save_sr );
175
176    return 0;
177} // hal_strcpy_from_uspace()
178
179////////////////////////////////////////////
180error_t hal_strcpy_to_uspace( char     * u_dst,
181                              char     * k_src,
182                              uint32_t   max_size )
183{
184
185// TODO implement the max_size handling, and error handling
186
187    uint32_t save_sr;
188    uint32_t src = (uint32_t)k_src;
189    uint32_t dst = (uint32_t)u_dst;
190
191    hal_disable_irq( &save_sr );
192
193    // loop on characters while non NUL
194    asm volatile(
195        "mfc2   $15,   $1           \n"   /* save current MMU_MODE          */
196        "1:                         \n"   /* loop entry                     */
197        "lb         $13,   0(%0)        \n"   /* read char from kernel space    */
198        "ori    $14,   $0,  0x7     \n" 
199        "mtc2   $14,   $1                       \n"   /* MMU_MODE <= DTLB ON            */
200            "sb     $13,   0(%1)        \n"   /* store char to user space       */
201        "mtc2   $15,   $1                       \n"   /* restore MMU_MODE               */
202        "addi   %0,    %0,  1       \n"   /* increment SRC pointer          */
203        "addi   %1,    %1,  1       \n"   /* increment DST pointer          */
204        "bne    $13,   $0,  1b      \n"   /* test NUL                       */
205        "nop                        \n"
206        : : "r"( src ) , "r"( dst ) : "$13","$14","$15", "memory" );
207
208    hal_restore_irq( save_sr );
209
210    return 0;
211} // hal_strcpy_to_uspace()
212
213///////////////////////////////////////////////
214uint32_t hal_strlen_from_uspace( char * u_str )
215{
216    uint32_t save_sr;
217    uint32_t str      = (uint32_t)u_str;
218    uint32_t count    = 0;
219
220    hal_disable_irq( &save_sr ); 
221
222        asm volatile(
223        "ori    $15,   %0,   0      \n"   /* $15 <= count                   */
224        "ori    $13,   %1,   0      \n"   /* $13 <= str                     */
225   
226        "mfc2   $15,   $1           \n"   /* save   MMU_MODE                */
227        "ori    $14,   $0,   0x7    \n"   /* $14 <= mode DTLB on            */
228        "mtc2   $14,   $1                       \n"   /* MMU_MODE <= DTLB ON            */
229
230        "1:                         \n"
231        "lb         $13,   0(%0)        \n"   /* read char from kernel space    */
232        "addi   $13,   $13,  1      \n"   /* increment address              */
233        "bne    $13,   $0,   1b     \n"   /* loop until NUL found           */
234        "addi   $15,   $15,  1      \n"   /* increment counter              */
235
236        "mtc2   $14,   $1                       \n"   /* restore MMU_MODE               */
237        : "+r"(count) : "r"(str) : "$13","$14","$15" );
238
239    hal_restore_irq( save_sr );
240
241    return count;
242}
243
Note: See TracBrowser for help on using the repository browser.