| [1] | 1 | /* | 
|---|
| [23] | 2 | * sys_read.c - read bytes from a file | 
|---|
| [1] | 3 | * | 
|---|
| [23] | 4 | * Author     Alain Greiner (2016,2017) | 
|---|
| [1] | 5 | * | 
|---|
| [23] | 6 | * Copyright (c) UPMC Sorbonne Universites | 
|---|
| [1] | 7 | * | 
|---|
| [23] | 8 | * This file is part of ALMOS-MKH. | 
|---|
|  | 9 | * | 
|---|
|  | 10 | * ALMOS-MKH is free software; you can redistribute it and/or modify it | 
|---|
| [1] | 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 | * | 
|---|
| [23] | 14 | * ALMOS-MKH is distributed in the hope that it will be useful, but | 
|---|
| [1] | 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 | 
|---|
| [23] | 20 | * along with ALMOS-MKH; if not, write to the Free Software Foundation, | 
|---|
| [1] | 21 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 
|---|
|  | 22 | */ | 
|---|
|  | 23 |  | 
|---|
| [23] | 24 | #include <kernel_config.h> | 
|---|
|  | 25 | #include <hal_types.h> | 
|---|
|  | 26 | #include <hal_uspace.h> | 
|---|
|  | 27 | #include <hal_special.h> | 
|---|
| [1] | 28 | #include <errno.h> | 
|---|
| [23] | 29 | #include <vfs.h> | 
|---|
|  | 30 | #include <vmm.h> | 
|---|
| [1] | 31 | #include <thread.h> | 
|---|
| [23] | 32 | #include <printk.h> | 
|---|
|  | 33 | #include <process.h> | 
|---|
| [1] | 34 |  | 
|---|
| [407] | 35 | // TODO: concurrent user page(s) munmap need to be handled [AG] | 
|---|
| [23] | 36 |  | 
|---|
| [407] | 37 | // instrumentation | 
|---|
|  | 38 | extern uint32_t enter_sys_read; | 
|---|
|  | 39 | extern uint32_t enter_devfs_move; | 
|---|
|  | 40 | extern uint32_t enter_txt_read; | 
|---|
|  | 41 | extern uint32_t enter_chdev_cmd; | 
|---|
|  | 42 | extern uint32_t enter_chdev_server; | 
|---|
|  | 43 | extern uint32_t enter_tty_cmd; | 
|---|
|  | 44 | extern uint32_t enter_tty_isr; | 
|---|
|  | 45 | extern uint32_t exit_tty_isr; | 
|---|
|  | 46 | extern uint32_t exit_tty_cmd; | 
|---|
|  | 47 | extern uint32_t exit_chdev_server; | 
|---|
|  | 48 | extern uint32_t exit_chdev_cmd; | 
|---|
|  | 49 | extern uint32_t exit_txt_read; | 
|---|
|  | 50 | extern uint32_t exit_devfs_move; | 
|---|
|  | 51 | extern uint32_t exit_sys_read; | 
|---|
|  | 52 |  | 
|---|
|  | 53 |  | 
|---|
| [23] | 54 | ///////////////////////////////// | 
|---|
|  | 55 | int sys_read( uint32_t   file_id, | 
|---|
| [407] | 56 | void     * vaddr, | 
|---|
| [23] | 57 | uint32_t   count ) | 
|---|
| [1] | 58 | { | 
|---|
| [23] | 59 | error_t      error; | 
|---|
| [313] | 60 | paddr_t      paddr;       // required for user space checking | 
|---|
| [23] | 61 | xptr_t       file_xp;     // remote file extended pointer | 
|---|
| [407] | 62 | uint32_t     nbytes;      // number of bytes actually read | 
|---|
| [408] | 63 | reg_t        save_sr;     // required to enable IRQs during syscall | 
|---|
| [407] | 64 | uint32_t     tm_start; | 
|---|
|  | 65 | uint32_t     tm_end; | 
|---|
|  | 66 |  | 
|---|
|  | 67 | tm_start = hal_get_cycles(); | 
|---|
|  | 68 |  | 
|---|
|  | 69 | #if CONFIG_READ_START | 
|---|
|  | 70 | enter_sys_read = tm_start; | 
|---|
|  | 71 | #endif | 
|---|
|  | 72 |  | 
|---|
| [23] | 73 | thread_t  *  this    = CURRENT_THREAD; | 
|---|
|  | 74 | process_t *  process = this->process; | 
|---|
|  | 75 |  | 
|---|
|  | 76 | // check file_id argument | 
|---|
|  | 77 | if( file_id >= CONFIG_PROCESS_FILE_MAX_NR ) | 
|---|
| [1] | 78 | { | 
|---|
| [23] | 79 | printk("\n[ERROR] in %s : illegal file descriptor index = %d\n", | 
|---|
| [407] | 80 | __FUNCTION__ , file_id ); | 
|---|
| [23] | 81 | this->errno = EBADFD; | 
|---|
| [1] | 82 | return -1; | 
|---|
|  | 83 | } | 
|---|
|  | 84 |  | 
|---|
| [23] | 85 | // check user buffer in user space | 
|---|
| [407] | 86 | error = vmm_v2p_translate( false , vaddr , &paddr ); | 
|---|
| [23] | 87 |  | 
|---|
|  | 88 | if ( error ) | 
|---|
|  | 89 | { | 
|---|
|  | 90 | printk("\n[ERROR] in %s : user buffer unmapped = %x\n", | 
|---|
| [407] | 91 | __FUNCTION__ , (intptr_t)vaddr ); | 
|---|
| [23] | 92 | this->errno = EINVAL; | 
|---|
|  | 93 | return -1; | 
|---|
|  | 94 | } | 
|---|
|  | 95 |  | 
|---|
| [408] | 96 | // enable IRQs | 
|---|
|  | 97 | hal_enable_irq( &save_sr ); | 
|---|
|  | 98 |  | 
|---|
| [23] | 99 | // get extended pointer on remote file descriptor | 
|---|
|  | 100 | file_xp = process_fd_get_xptr( process , file_id ); | 
|---|
|  | 101 |  | 
|---|
|  | 102 | if( file_xp == XPTR_NULL ) | 
|---|
|  | 103 | { | 
|---|
| [407] | 104 | printk("\n[ERROR] in %s : undefined file descriptor index = %d in process %x\n", | 
|---|
|  | 105 | __FUNCTION__ , file_id , process->pid ); | 
|---|
| [23] | 106 | this->errno = EBADFD; | 
|---|
|  | 107 | return -1; | 
|---|
|  | 108 | } | 
|---|
|  | 109 |  | 
|---|
|  | 110 | // get file descriptor cluster and local pointer | 
|---|
|  | 111 | vfs_file_t * file_ptr = (vfs_file_t *)GET_PTR( file_xp ); | 
|---|
|  | 112 | cxy_t        file_cxy = GET_CXY( file_xp ); | 
|---|
|  | 113 |  | 
|---|
|  | 114 | // check file readable | 
|---|
|  | 115 | uint32_t attr = hal_remote_lw( XPTR( file_cxy , &file_ptr->attr ) ); | 
|---|
|  | 116 | if( (attr & FD_ATTR_READ_ENABLE) == 0 ) | 
|---|
| [1] | 117 | { | 
|---|
| [407] | 118 | printk("\n[ERROR] in %s : file %d not readable in process %x\n", | 
|---|
|  | 119 | __FUNCTION__ , file_id , process->pid ); | 
|---|
| [23] | 120 | this->errno = EBADFD; | 
|---|
| [1] | 121 | return -1; | 
|---|
|  | 122 | } | 
|---|
| [313] | 123 |  | 
|---|
| [407] | 124 | // get file type | 
|---|
|  | 125 | vfs_inode_type_t type = hal_remote_lw( XPTR( file_cxy , &file_ptr->type ) ); | 
|---|
| [313] | 126 |  | 
|---|
| [407] | 127 | // action depend on file type | 
|---|
|  | 128 | if( type == INODE_TYPE_FILE )      // transfer count bytes from file mapper | 
|---|
| [23] | 129 | { | 
|---|
| [407] | 130 | nbytes = vfs_user_move( true,               // from mapper to buffer | 
|---|
|  | 131 | file_xp, | 
|---|
|  | 132 | vaddr, | 
|---|
|  | 133 | count ); | 
|---|
|  | 134 | } | 
|---|
|  | 135 | else if( type == INODE_TYPE_DEV )  // transfer count bytes from device | 
|---|
|  | 136 | { | 
|---|
|  | 137 | nbytes = devfs_user_move( true,             // from device to buffer | 
|---|
|  | 138 | file_xp, | 
|---|
|  | 139 | vaddr, | 
|---|
|  | 140 | count ); | 
|---|
|  | 141 | } | 
|---|
|  | 142 | else | 
|---|
|  | 143 | { | 
|---|
|  | 144 | nbytes = 0; | 
|---|
|  | 145 | panic("file type %d non supported yet", type ); | 
|---|
|  | 146 | } | 
|---|
|  | 147 |  | 
|---|
|  | 148 | if( nbytes != count ) | 
|---|
|  | 149 | { | 
|---|
|  | 150 | printk("\n[ERROR] in %s cannot read data from file %d in process %x\n", | 
|---|
|  | 151 | __FUNCTION__ , file_id , process->pid ); | 
|---|
| [313] | 152 | this->errno = error; | 
|---|
|  | 153 | return -1; | 
|---|
| [23] | 154 | } | 
|---|
|  | 155 |  | 
|---|
| [408] | 156 | // restore IRQs | 
|---|
|  | 157 | hal_restore_irq( save_sr ); | 
|---|
|  | 158 |  | 
|---|
| [124] | 159 | hal_fence(); | 
|---|
| [23] | 160 |  | 
|---|
| [407] | 161 | tm_end = hal_get_cycles(); | 
|---|
| [23] | 162 |  | 
|---|
| [407] | 163 | #if CONFIG_READ_DEBUG | 
|---|
|  | 164 | exit_sys_read = tm_end; | 
|---|
|  | 165 |  | 
|---|
|  | 166 | printk("\n@@@@@@@@@@@@ timing ro read character %c\n" | 
|---|
|  | 167 | " - enter_sys_read     = %d / delta %d\n" | 
|---|
|  | 168 | " - enter_devfs_move   = %d / delta %d\n" | 
|---|
|  | 169 | " - enter_txt_read     = %d / delta %d\n" | 
|---|
|  | 170 | " - enter_chdev_cmd    = %d / delta %d\n" | 
|---|
|  | 171 | " - enter_chdev_server = %d / delta %d\n" | 
|---|
|  | 172 | " - enter_tty_cmd      = %d / delta %d\n" | 
|---|
|  | 173 | " - enter_tty_isr      = %d / delta %d\n" | 
|---|
|  | 174 | " - exit_tty_isr       = %d / delta %d\n" | 
|---|
|  | 175 | " - exit_tty_cmd       = %d / delta %d\n" | 
|---|
|  | 176 | " - exit_chdev_server  = %d / delta %d\n" | 
|---|
|  | 177 | " - exit_chdev_cmd     = %d / delta %d\n" | 
|---|
|  | 178 | " - exit_txt_read      = %d / delta %d\n" | 
|---|
|  | 179 | " - exit_devfs_move    = %d / delta %d\n" | 
|---|
|  | 180 | " - exit_sys_read      = %d / delta %d\n", | 
|---|
|  | 181 | *((char *)(intptr_t)paddr) , | 
|---|
|  | 182 | enter_sys_read     , 0 , | 
|---|
|  | 183 | enter_devfs_move   , enter_devfs_move   - enter_sys_read     , | 
|---|
|  | 184 | enter_txt_read     , enter_txt_read     - enter_devfs_move   , | 
|---|
|  | 185 | enter_chdev_cmd    , enter_chdev_cmd    - enter_txt_read     , | 
|---|
|  | 186 | enter_chdev_server , enter_chdev_server - enter_chdev_cmd    , | 
|---|
|  | 187 | enter_tty_cmd      , enter_tty_cmd      - enter_chdev_server , | 
|---|
|  | 188 | enter_tty_isr      , enter_tty_isr      - enter_tty_cmd      , | 
|---|
|  | 189 | exit_tty_isr       , exit_tty_isr       - enter_tty_isr      , | 
|---|
|  | 190 | exit_tty_cmd       , exit_tty_cmd       - exit_tty_isr       , | 
|---|
|  | 191 | exit_chdev_server  , exit_chdev_server  - exit_tty_cmd       , | 
|---|
|  | 192 | exit_chdev_cmd     , exit_chdev_cmd     - exit_chdev_server  , | 
|---|
|  | 193 | exit_txt_read      , exit_txt_read      - exit_chdev_cmd     , | 
|---|
|  | 194 | exit_devfs_move    , exit_devfs_move    - exit_txt_read      , | 
|---|
|  | 195 | exit_sys_read      , exit_sys_read      - exit_devfs_move    ); | 
|---|
|  | 196 | #endif | 
|---|
|  | 197 |  | 
|---|
| [408] | 198 | syscall_dmsg("\n[DBG] %s : core[%x,%d] / thread %x in process %x / cycle %d\n" | 
|---|
|  | 199 | "nbytes = %d / first byte = %c / file_id = %d / cost = %d\n", | 
|---|
|  | 200 | __FUNCTION__ , local_cxy , this->core->lid , this->trdid , this->process->pid , | 
|---|
|  | 201 | tm_start , nbytes , *((char *)(intptr_t)paddr) , file_id , tm_end - tm_start ); | 
|---|
| [407] | 202 |  | 
|---|
|  | 203 | return nbytes; | 
|---|
|  | 204 |  | 
|---|
| [23] | 205 | }  // end sys_read() | 
|---|