Changeset 7918fce in mainline


Ignore:
Timestamp:
2007-07-11T20:31:45Z (17 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
975f62f
Parents:
398d967
Message:

Implement a new mechanism for copying data between two address spaces based on
IPC. New system method IPC_M_DATA_SEND is introduced. The implementation is
generic and does not make use of any possible architecture optimizations such as
direct copy from one address space to another.

Location:
kernel/generic
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/include/ipc/ipc.h

    r398d967 r7918fce  
    139139#define IPC_M_PHONE_HUNGUP      3
    140140
    141 /** Send as_area over IPC 
    142  * - ARG1 - src as_area base address
    143  * - ARG2 - size of src as_area (filled automatically by kernel)
     141/** Send as_area over IPC.
     142 * - ARG1 - source as_area base address
     143 * - ARG2 - size of source as_area (filled automatically by kernel)
    144144 * - ARG3 - flags of the as_area being sent
    145145 *
    146  * on answer:
     146 * on answer, the recipient must set:
    147147 * - ARG1 - dst as_area base adress
    148148 */
    149149#define IPC_M_AS_AREA_SEND      4       
    150150
    151 /** Get as_area over IPC
    152  * - ARG1 - dst as_area base address
    153  * - ARG2 - dst as_area size
     151/** Receive as_area over IPC.
     152 * - ARG1 - destination as_area base address
     153 * - ARG2 - destination as_area size
    154154 * - ARG3 - user defined argument
    155155 *
    156  * on answer, the server must set:
    157  *
    158  * - ARG1 - src as_area base address
     156 * on answer, the recipient must set:
     157 *
     158 * - ARG1 - source as_area base address
    159159 * - ARG2 - flags that will be used for sharing
    160160 */
    161161#define IPC_M_AS_AREA_RECV      5       
    162162
     163/** Send data to another address space over IPC.
     164 * - ARG1 - destination address space virtual address, may be overriden by the
     165 *          recipient
     166 * - ARG2 - source address space virtual address
     167 * - ARG3 - size of data to be copied, may be overriden by the recipient
     168 *
     169 * on answer, the recipient must set:
     170 *
     171 * - ARG1 - final destination address space virtual address
     172 * - ARG3 - final size of data to be copied
     173 */
     174#define IPC_M_DATA_SEND         6
    163175
    164176/* Well-known methods */
     
    243255        /** Data passed from/to userspace. */
    244256        ipc_data_t data;
     257
     258        /** Buffer for IPC_M_DATA_SEND. */
     259        uint8_t *buffer;
    245260} call_t;
    246261
  • kernel/generic/src/ipc/ipc.c

    r398d967 r7918fce  
    6868        call->callerbox = &TASK->answerbox;
    6969        call->sender = TASK;
     70        call->buffer = NULL;
    7071}
    7172
     
    108109{
    109110        ASSERT(!(call->flags & IPC_CALL_STATIC_ALLOC));
     111        /* Check to see if we have data in the IPC_M_DATA_SEND buffer. */
     112        if (call->buffer)
     113                free(call->buffer);
    110114        slab_free(ipc_call_slab, call);
    111115}
     
    293297       
    294298        spinlock_lock(&phone->lock);
    295         if (phone->state == IPC_PHONE_FREE || phone->state == IPC_PHONE_HUNGUP ||
     299        if (phone->state == IPC_PHONE_FREE ||
     300            phone->state == IPC_PHONE_HUNGUP ||
    296301            phone->state == IPC_PHONE_CONNECTING) {
    297302                spinlock_unlock(&phone->lock);
  • kernel/generic/src/ipc/sysipc.c

    r398d967 r7918fce  
    5050#include <print.h>
    5151
     52/** Maximum buffer size allowed for IPC_M_DATA_SEND requests. */
     53#define DATA_SEND_LIMIT         (64 * 1024)
     54
    5255#define GET_CHECK_PHONE(phone, phoneid, err) \
    5356{ \
     
    8689static inline int is_forwardable(unative_t method)
    8790{
    88         if (method == IPC_M_PHONE_HUNGUP || method == IPC_M_AS_AREA_SEND ||
    89             method == IPC_M_AS_AREA_RECV)
    90                 return 0; /* This message is meant only for the receiver */
    91         return 1;
     91        switch (method) {
     92        case IPC_M_PHONE_HUNGUP:
     93        case IPC_M_AS_AREA_SEND:
     94        case IPC_M_AS_AREA_RECV:
     95        case IPC_M_DATA_SEND:
     96                /* This message is meant only for the original recipient. */
     97                return 0;
     98        default:
     99                return 1;
     100        }
    92101}
    93102
     
    107116static inline int answer_need_old(call_t *call)
    108117{
    109         if (IPC_GET_METHOD(call->data) == IPC_M_CONNECT_TO_ME)
     118        switch (IPC_GET_METHOD(call->data)) {
     119        case IPC_M_CONNECT_TO_ME:
     120        case IPC_M_CONNECT_ME_TO:
     121        case IPC_M_AS_AREA_SEND:
     122        case IPC_M_AS_AREA_RECV:
     123        case IPC_M_DATA_SEND:
    110124                return 1;
    111         if (IPC_GET_METHOD(call->data) == IPC_M_CONNECT_ME_TO)
    112                 return 1;
    113         if (IPC_GET_METHOD(call->data) == IPC_M_AS_AREA_SEND)
    114                 return 1;
    115         if (IPC_GET_METHOD(call->data) == IPC_M_AS_AREA_RECV)
    116                 return 1;
    117         return 0;
     125        default:
     126                return 0;
     127        }
    118128}
    119129
     
    202212                        IPC_SET_RETVAL(answer->data, rc);
    203213                }
     214        } else if (IPC_GET_METHOD(*olddata) == IPC_M_DATA_SEND) {
     215                if (!IPC_GET_RETVAL(answer->data)) {
     216                        int rc;
     217                        uintptr_t dst;
     218                        uintptr_t size;
     219
     220                        ASSERT(answer->buffer);
     221
     222                        dst = IPC_GET_ARG1(answer->data);
     223                        size = IPC_GET_ARG3(answer->data);
     224
     225                        rc = copy_to_uspace((void *) dst, answer->buffer, size);
     226                        if (rc != 0)
     227                                IPC_SET_RETVAL(answer->data, rc);
     228                        free(answer->buffer);
     229                        answer->buffer = NULL;
     230                }
    204231        }
    205232        return 0;
     
    216243        int newphid;
    217244        size_t size;
     245        uintptr_t src;
     246        int rc;
    218247
    219248        switch (IPC_GET_METHOD(call->data)) {
     
    233262                IPC_SET_ARG2(call->data, size);
    234263                break;
     264        case IPC_M_DATA_SEND:
     265                src = IPC_GET_ARG2(call->data);
     266                size = IPC_GET_ARG3(call->data);
     267               
     268                if ((size <= 0) || (size > DATA_SEND_LIMIT))
     269                        return ELIMIT;
     270               
     271                call->buffer = (uint8_t *) malloc(size, 0);
     272                rc = copy_from_uspace(call->buffer, (void *) src, size);
     273                if (rc != 0) {
     274                        free(call->buffer);
     275                        return rc;
     276                }
     277                break;
    235278        default:
    236279                break;
     
    327370 * @param phoneid       Phone handle for the call.
    328371 * @param question      Userspace address of call data with the request.
    329  * @param reply         Userspace address of call data where to store the answer.
     372 * @param reply         Userspace address of call data where to store the
     373 *                      answer.
    330374 *
    331375 * @return              Zero on success or an error code.
Note: See TracChangeset for help on using the changeset viewer.