Ignore:
Timestamp:
Apr 29, 2019, 7:25:09 PM (5 years ago)
Author:
alain
Message:

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:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/hal/tsar_mips32/core/hal_uspace.c

    r625 r626  
    22 * hal_uspace.c - implementation of Generic User Space Access API for MIPS32
    33 *
    4  * Author  Mohamed Karaoui (2015)
    5  *         Alain Greiner   (2016)
     4 * Author        Alain Greiner   (2016,2017,2018,2019)
    65 *
    76 * Copyright (c) UPMC Sorbonne Universites
     
    2322 */
    2423
    25 #include <errno.h>
    26 #include <vmm.h>
    2724#include <hal_kernel_types.h>
    2825#include <hal_uspace.h>
     26#include <hal_special.h>
    2927#include <hal_irqmask.h>
    3028
     
    3230#include <thread.h>
    3331
    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///////////////////////////////////////////////////////////////////////////////////////
     48void hal_copy_from_uspace( cxy_t      k_cxy,
     49                           void     * k_dst,
    3650                           void     * u_src,
    3751                           uint32_t   size ) 
    3852{
    3953    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)
    4255    uint32_t src = (uint32_t)u_src;
    4356    uint32_t dst = (uint32_t)k_dst;
    44 
     57 
    4558#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 );
     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 );
    4964#endif
    5065
    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
    5470    hal_disable_irq( &save_sr );
    5571
    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
    87124    hal_restore_irq( save_sr );
    88125
    89126#if DEBUG_HAL_USPACE
    90 printk("\n[%s] thread[%x,%x] exit\n",
    91 __FUNCTION__, this->process->pid, this->trdid );
     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 );
    92131#endif
    93132
    94133}  // end hal_copy_from_uspace()
    95134
    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///////////////////////////////////////////////////////////////////////////////////////
     151void hal_copy_to_uspace( cxy_t      k_cxy,
    98152                         void     * k_src,
     153                         void     * u_dst,
    99154                         uint32_t   size )
    100155{
    101156    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)
    104158    uint32_t src = (uint32_t)k_src;
    105159    uint32_t dst = (uint32_t)u_dst;
    106160
    107161#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 );
     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 );
    111167#endif
    112168
    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
    116173    hal_disable_irq( &save_sr );
    117174
    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
    148227    hal_restore_irq( save_sr );
    149228
    150229#if DEBUG_HAL_USPACE
    151 printk("\n[%s] thread[%x,%x] exit\n",
    152 __FUNCTION__, this->process->pid, this->trdid );
     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 );
    153234#endif
    154235
Note: See TracChangeset for help on using the changeset viewer.