Changeset e8039a86 in mainline
- Timestamp:
- 2012-08-20T23:21:41Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 0343a1b
- Parents:
- 642dc72
- Location:
- kernel/generic
- Files:
-
- 15 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/include/config.h
r642dc72 re8039a86 47 47 #define CONFIG_INIT_TASKS 32 48 48 #define CONFIG_TASK_NAME_BUFLEN 32 49 50 /** 51 * Maximum buffer size allowed for IPC_M_DATA_WRITE and IPC_M_DATA_READ 52 * requests. 53 */ 54 #define DATA_XFER_LIMIT (64 * 1024) 49 55 50 56 #ifndef __ASM__ -
kernel/generic/include/ipc/ipcrsc.h
r642dc72 re8039a86 40 40 41 41 extern call_t *get_call(sysarg_t); 42 extern int phone_get(sysarg_t, phone_t **); 42 43 extern int phone_alloc(task_t *); 43 44 extern void phone_connect(int, answerbox_t *); -
kernel/generic/src/ipc/ipcrsc.c
r642dc72 re8039a86 132 132 #include <ipc/ipcrsc.h> 133 133 #include <debug.h> 134 #include <abi/errno.h> 134 135 135 136 /** Find call_t * in call table according to callid. … … 160 161 irq_spinlock_unlock(&TASK->answerbox.lock, true); 161 162 return result; 163 } 164 165 /** Get phone from the current task by ID. 166 * 167 * @param phoneid Phone ID. 168 * @param phone Place to store pointer to phone. 169 * 170 * @return EOK on success, EINVAL if ID is invalid. 171 * 172 */ 173 int phone_get(sysarg_t phoneid, phone_t **phone) 174 { 175 if (phoneid >= IPC_MAX_PHONES) 176 return EINVAL; 177 178 *phone = &TASK->phones[phoneid]; 179 return EOK; 162 180 } 163 181 -
kernel/generic/src/ipc/ops/clnestab.c
r642dc72 re8039a86 34 34 35 35 #include <ipc/sysipc_ops.h> 36 #include <ipc/ipc.h> 37 #include <synch/mutex.h> 38 #include <abi/errno.h> 39 40 static int request_preprocess(call_t *call, phone_t *phone) 41 { 42 IPC_SET_ARG5(call->data, (sysarg_t) phone); 43 44 return EOK; 45 } 46 47 static int answer_preprocess(call_t *answer, ipc_data_t *olddata) 48 { 49 phone_t *phone = (phone_t *) IPC_GET_ARG5(*olddata); 50 51 if (IPC_GET_RETVAL(answer->data) != EOK) { 52 /* 53 * The other party on the cloned phone rejected our request 54 * for connection on the protocol level. We need to break the 55 * connection without sending IPC_M_HUNGUP back. 56 */ 57 mutex_lock(&phone->lock); 58 if (phone->state == IPC_PHONE_CONNECTED) { 59 irq_spinlock_lock(&phone->callee->lock, true); 60 list_remove(&phone->link); 61 phone->state = IPC_PHONE_SLAMMED; 62 irq_spinlock_unlock(&phone->callee->lock, true); 63 } 64 mutex_unlock(&phone->lock); 65 } 66 67 return EOK; 68 } 36 69 37 70 sysipc_ops_t ipc_m_clone_establish_ops = { 38 .request_preprocess = null_request_preprocess,71 .request_preprocess = request_preprocess, 39 72 .request_process = null_request_process, 40 .answer_preprocess = null_answer_preprocess,73 .answer_preprocess = answer_preprocess, 41 74 .answer_process = null_answer_process, 42 75 }; -
kernel/generic/src/ipc/ops/conctmeto.c
r642dc72 re8039a86 1 1 /* 2 * Copyright (c) 2006 Ondrej Palkovsky 2 3 * Copyright (c) 2012 Jakub Jermar 3 4 * All rights reserved. … … 34 35 35 36 #include <ipc/sysipc_ops.h> 37 #include <ipc/ipc.h> 38 #include <ipc/ipcrsc.h> 39 #include <abi/errno.h> 40 #include <arch.h> 36 41 37 static sysipc_ops_t ipc_m_connect_me_to_ops = { 38 .request_preprocess = null_request_preprocess, 42 static int request_preprocess(call_t *call, phone_t *phone) 43 { 44 int newphid = phone_alloc(TASK); 45 46 if (newphid < 0) 47 return ELIMIT; 48 49 /* Set arg5 for server */ 50 IPC_SET_ARG5(call->data, (sysarg_t) &TASK->phones[newphid]); 51 call->flags |= IPC_CALL_CONN_ME_TO; 52 call->priv = newphid; 53 54 return EOK; 55 } 56 57 static int answer_preprocess(call_t *answer, ipc_data_t *olddata) 58 { 59 phone_t *phone = (phone_t *) IPC_GET_ARG5(*olddata); 60 61 /* If the user accepted call, connect */ 62 if (IPC_GET_RETVAL(answer->data) == EOK) 63 ipc_phone_connect(phone, &TASK->answerbox); 64 65 return EOK; 66 } 67 68 69 sysipc_ops_t ipc_m_connect_me_to_ops = { 70 .request_preprocess = request_preprocess, 39 71 .request_process = null_request_process, 40 .answer_preprocess = null_answer_preprocess,72 .answer_preprocess = answer_preprocess, 41 73 .answer_process = null_answer_process, 42 74 }; 43 75 44 sysipc_ops_t *ipc_m_connect_me_to_ops_p = &ipc_m_connect_me_to_ops;45 46 76 /** @} 47 77 */ -
kernel/generic/src/ipc/ops/concttome.c
r642dc72 re8039a86 1 1 /* 2 * Copyright (c) 2006 Ondrej Palkovsky 2 3 * Copyright (c) 2012 Jakub Jermar 3 4 * All rights reserved. … … 34 35 35 36 #include <ipc/sysipc_ops.h> 37 #include <ipc/ipc.h> 38 #include <ipc/ipcrsc.h> 39 #include <abi/errno.h> 40 #include <arch.h> 41 42 static int request_process(call_t *call, answerbox_t *box) 43 { 44 int phoneid = phone_alloc(TASK); 45 46 if (phoneid < 0) { /* Failed to allocate phone */ 47 IPC_SET_RETVAL(call->data, ELIMIT); 48 ipc_answer(box, call); 49 return -1; 50 } 51 52 IPC_SET_ARG5(call->data, phoneid); 53 54 return EOK; 55 } 56 57 static int answer_preprocess(call_t *answer, ipc_data_t *olddata) 58 { 59 int phoneid = (int) IPC_GET_ARG5(*olddata); 60 61 if (IPC_GET_RETVAL(answer->data) != EOK) { 62 /* The connection was not accepted */ 63 int phoneid = (int) IPC_GET_ARG5(*olddata); 64 65 phone_dealloc(phoneid); 66 } else { 67 /* The connection was accepted */ 68 phone_connect(phoneid, &answer->sender->answerbox); 69 /* Set 'phone hash' as arg5 of response */ 70 IPC_SET_ARG5(answer->data, (sysarg_t) &TASK->phones[phoneid]); 71 } 72 73 return EOK; 74 } 75 36 76 37 77 sysipc_ops_t ipc_m_connect_to_me_ops = { 38 78 .request_preprocess = null_request_preprocess, 39 .request_process = null_request_process,40 .answer_preprocess = null_answer_preprocess,79 .request_process = request_process, 80 .answer_preprocess = answer_preprocess, 41 81 .answer_process = null_answer_process, 42 82 }; -
kernel/generic/src/ipc/ops/connclone.c
r642dc72 re8039a86 34 34 35 35 #include <ipc/sysipc_ops.h> 36 #include <ipc/ipc.h> 37 #include <ipc/ipcrsc.h> 38 #include <synch/mutex.h> 39 #include <abi/errno.h> 40 #include <arch.h> 41 42 static void phones_lock(phone_t *p1, phone_t *p2) 43 { 44 if (p1 < p2) { 45 mutex_lock(&p1->lock); 46 mutex_lock(&p2->lock); 47 } else if (p1 > p2) { 48 mutex_lock(&p2->lock); 49 mutex_lock(&p1->lock); 50 } else 51 mutex_lock(&p1->lock); 52 } 53 54 static void phones_unlock(phone_t *p1, phone_t *p2) 55 { 56 mutex_unlock(&p1->lock); 57 if (p1 != p2) 58 mutex_unlock(&p2->lock); 59 } 60 61 static int request_preprocess(call_t *call, phone_t *phone) 62 { 63 phone_t *cloned_phone; 64 65 if (phone_get(IPC_GET_ARG1(call->data), &cloned_phone) != EOK) 66 return ENOENT; 67 68 phones_lock(cloned_phone, phone); 69 70 if ((cloned_phone->state != IPC_PHONE_CONNECTED) || 71 phone->state != IPC_PHONE_CONNECTED) { 72 phones_unlock(cloned_phone, phone); 73 return EINVAL; 74 } 75 76 /* 77 * We can be pretty sure now that both tasks exist and we are 78 * connected to them. As we continue to hold the phone locks, 79 * we are effectively preventing them from finishing their 80 * potential cleanup. 81 * 82 */ 83 int newphid = phone_alloc(phone->callee->task); 84 if (newphid < 0) { 85 phones_unlock(cloned_phone, phone); 86 return ELIMIT; 87 } 88 89 ipc_phone_connect(&phone->callee->task->phones[newphid], 90 cloned_phone->callee); 91 phones_unlock(cloned_phone, phone); 92 93 /* Set the new phone for the callee. */ 94 IPC_SET_ARG1(call->data, newphid); 95 96 return EOK; 97 } 98 99 static int answer_preprocess(call_t *answer, ipc_data_t *olddata) 100 { 101 if (IPC_GET_RETVAL(answer->data) != EOK) { 102 /* 103 * The recipient of the cloned phone rejected the offer. 104 */ 105 int phoneid = (int) IPC_GET_ARG1(*olddata); 106 phone_t *phone = &TASK->phones[phoneid]; 107 108 /* 109 * In this case, the connection was established at the request 110 * time and therefore we need to slam the phone. We don't 111 * merely hangup as that would result in sending IPC_M_HUNGUP 112 * to the third party on the other side of the cloned phone. 113 */ 114 mutex_lock(&phone->lock); 115 if (phone->state == IPC_PHONE_CONNECTED) { 116 irq_spinlock_lock(&phone->callee->lock, true); 117 list_remove(&phone->link); 118 phone->state = IPC_PHONE_SLAMMED; 119 irq_spinlock_unlock(&phone->callee->lock, true); 120 } 121 mutex_unlock(&phone->lock); 122 } 123 124 return EOK; 125 } 36 126 37 127 sysipc_ops_t ipc_m_connection_clone_ops = { 38 .request_preprocess = null_request_preprocess,128 .request_preprocess = request_preprocess, 39 129 .request_process = null_request_process, 40 .answer_preprocess = null_answer_preprocess,130 .answer_preprocess = answer_preprocess, 41 131 .answer_process = null_answer_process, 42 132 }; -
kernel/generic/src/ipc/ops/dataread.c
r642dc72 re8039a86 34 34 35 35 #include <ipc/sysipc_ops.h> 36 #include <ipc/ipc.h> 37 #include <mm/slab.h> 38 #include <abi/errno.h> 39 #include <syscall/copy.h> 40 #include <config.h> 41 42 static int request_preprocess(call_t *call, phone_t *phone) 43 { 44 size_t size = IPC_GET_ARG2(call->data); 45 46 if (size > DATA_XFER_LIMIT) { 47 int flags = IPC_GET_ARG3(call->data); 48 49 if (flags & IPC_XF_RESTRICT) 50 IPC_SET_ARG2(call->data, DATA_XFER_LIMIT); 51 else 52 return ELIMIT; 53 } 54 55 return EOK; 56 } 57 58 static int answer_preprocess(call_t *answer, ipc_data_t *olddata) 59 { 60 ASSERT(!answer->buffer); 61 62 if (!IPC_GET_RETVAL(answer->data)) { 63 /* The recipient agreed to send data. */ 64 uintptr_t src = IPC_GET_ARG1(answer->data); 65 uintptr_t dst = IPC_GET_ARG1(*olddata); 66 size_t max_size = IPC_GET_ARG2(*olddata); 67 size_t size = IPC_GET_ARG2(answer->data); 68 if (size && size <= max_size) { 69 /* 70 * Copy the destination VA so that this piece of 71 * information is not lost. 72 */ 73 IPC_SET_ARG1(answer->data, dst); 74 75 answer->buffer = malloc(size, 0); 76 int rc = copy_from_uspace(answer->buffer, 77 (void *) src, size); 78 if (rc) { 79 IPC_SET_RETVAL(answer->data, rc); 80 free(answer->buffer); 81 answer->buffer = NULL; 82 } 83 } else if (!size) { 84 IPC_SET_RETVAL(answer->data, EOK); 85 } else { 86 IPC_SET_RETVAL(answer->data, ELIMIT); 87 } 88 } 89 90 return EOK; 91 } 36 92 37 93 sysipc_ops_t ipc_m_data_read_ops = { 38 .request_preprocess = null_request_preprocess,94 .request_preprocess = request_preprocess, 39 95 .request_process = null_request_process, 40 .answer_preprocess = null_answer_preprocess,96 .answer_preprocess = answer_preprocess, 41 97 .answer_process = null_answer_process, 42 98 }; -
kernel/generic/src/ipc/ops/datawrite.c
r642dc72 re8039a86 34 34 35 35 #include <ipc/sysipc_ops.h> 36 #include <ipc/ipc.h> 37 #include <mm/slab.h> 38 #include <abi/errno.h> 39 #include <syscall/copy.h> 40 #include <config.h> 41 42 static int request_preprocess(call_t *call, phone_t *phone) 43 { 44 uintptr_t src = IPC_GET_ARG1(call->data); 45 size_t size = IPC_GET_ARG2(call->data); 46 47 if (size > DATA_XFER_LIMIT) { 48 int flags = IPC_GET_ARG3(call->data); 49 50 if (flags & IPC_XF_RESTRICT) { 51 size = DATA_XFER_LIMIT; 52 IPC_SET_ARG2(call->data, size); 53 } else 54 return ELIMIT; 55 } 56 57 call->buffer = (uint8_t *) malloc(size, 0); 58 int rc = copy_from_uspace(call->buffer, (void *) src, size); 59 if (rc != 0) { 60 free(call->buffer); 61 return rc; 62 } 63 64 return EOK; 65 } 66 67 static int answer_preprocess(call_t *answer, ipc_data_t *olddata) 68 { 69 ASSERT(answer->buffer); 70 71 if (!IPC_GET_RETVAL(answer->data)) { 72 /* The recipient agreed to receive data. */ 73 uintptr_t dst = (uintptr_t)IPC_GET_ARG1(answer->data); 74 size_t size = (size_t)IPC_GET_ARG2(answer->data); 75 size_t max_size = (size_t)IPC_GET_ARG2(*olddata); 76 77 if (size <= max_size) { 78 int rc = copy_to_uspace((void *) dst, 79 answer->buffer, size); 80 if (rc) 81 IPC_SET_RETVAL(answer->data, rc); 82 } else { 83 IPC_SET_RETVAL(answer->data, ELIMIT); 84 } 85 } 86 free(answer->buffer); 87 answer->buffer = NULL; 88 89 return EOK; 90 } 91 36 92 37 93 sysipc_ops_t ipc_m_data_write_ops = { 38 .request_preprocess = null_request_preprocess,94 .request_preprocess = request_preprocess, 39 95 .request_process = null_request_process, 40 .answer_preprocess = null_answer_preprocess,96 .answer_preprocess = answer_preprocess, 41 97 .answer_process = null_answer_process, 42 98 }; -
kernel/generic/src/ipc/ops/debug.c
r642dc72 re8039a86 1 1 /* 2 * Copyright (c) 20 12 Jakub Jermar2 * Copyright (c) 2008 Jiri Svoboda 3 3 * All rights reserved. 4 4 * … … 34 34 35 35 #include <ipc/sysipc_ops.h> 36 #include <ipc/ipc.h> 37 #include <udebug/udebug_ipc.h> 38 39 static int request_process(call_t *call, answerbox_t *box) 40 { 41 return -1; 42 } 36 43 37 44 sysipc_ops_t ipc_m_debug_ops = { 45 #ifdef CONFIG_UDEBUG 46 .request_preprocess = udebug_request_preprocess, 47 #else 38 48 .request_preprocess = null_request_preprocess, 39 .request_process = null_request_process, 49 #endif 50 .request_process = request_process, 40 51 .answer_preprocess = null_answer_preprocess, 41 52 .answer_process = null_answer_process, -
kernel/generic/src/ipc/ops/sharein.c
r642dc72 re8039a86 34 34 35 35 #include <ipc/sysipc_ops.h> 36 #include <ipc/ipc.h> 37 #include <mm/as.h> 38 #include <synch/spinlock.h> 39 #include <proc/task.h> 40 #include <abi/errno.h> 41 #include <arch.h> 42 43 static int answer_preprocess(call_t *answer, ipc_data_t *olddata) 44 { 45 if (!IPC_GET_RETVAL(answer->data)) { 46 irq_spinlock_lock(&answer->sender->lock, true); 47 as_t *as = answer->sender->as; 48 irq_spinlock_unlock(&answer->sender->lock, true); 49 50 uintptr_t dst_base = (uintptr_t) -1; 51 int rc = as_area_share(AS, IPC_GET_ARG1(answer->data), 52 IPC_GET_ARG1(*olddata), as, IPC_GET_ARG2(answer->data), 53 &dst_base, IPC_GET_ARG3(answer->data)); 54 IPC_SET_ARG4(answer->data, dst_base); 55 IPC_SET_RETVAL(answer->data, rc); 56 } 57 58 return EOK; 59 } 36 60 37 61 sysipc_ops_t ipc_m_share_in_ops = { 38 62 .request_preprocess = null_request_preprocess, 39 63 .request_process = null_request_process, 40 .answer_preprocess = null_answer_preprocess,64 .answer_preprocess = answer_preprocess, 41 65 .answer_process = null_answer_process, 42 66 }; -
kernel/generic/src/ipc/ops/shareout.c
r642dc72 re8039a86 34 34 35 35 #include <ipc/sysipc_ops.h> 36 #include <ipc/ipc.h> 37 #include <mm/as.h> 38 #include <synch/spinlock.h> 39 #include <proc/task.h> 40 #include <syscall/copy.h> 41 #include <abi/errno.h> 42 #include <arch.h> 43 44 static int request_preprocess(call_t *call, phone_t *phone) 45 { 46 size_t size = as_area_get_size(IPC_GET_ARG1(call->data)); 47 48 if (!size) 49 return EPERM; 50 IPC_SET_ARG2(call->data, size); 51 52 return EOK; 53 } 54 55 static int answer_preprocess(call_t *answer, ipc_data_t *olddata) 56 { 57 int rc = EOK; 58 59 if (!IPC_GET_RETVAL(answer->data)) { 60 /* Accepted, handle as_area receipt */ 61 62 irq_spinlock_lock(&answer->sender->lock, true); 63 as_t *as = answer->sender->as; 64 irq_spinlock_unlock(&answer->sender->lock, true); 65 66 uintptr_t dst_base = (uintptr_t) -1; 67 rc = as_area_share(as, IPC_GET_ARG1(*olddata), 68 IPC_GET_ARG2(*olddata), AS, IPC_GET_ARG3(*olddata), 69 &dst_base, IPC_GET_ARG1(answer->data)); 70 71 if (rc == EOK) { 72 rc = copy_to_uspace((void *) IPC_GET_ARG2(answer->data), 73 &dst_base, sizeof(dst_base)); 74 } 75 76 IPC_SET_RETVAL(answer->data, rc); 77 } 78 79 return rc; 80 } 36 81 37 82 sysipc_ops_t ipc_m_share_out_ops = { 38 .request_preprocess = null_request_preprocess,83 .request_preprocess = request_preprocess, 39 84 .request_process = null_request_process, 40 .answer_preprocess = null_answer_preprocess,85 .answer_preprocess = answer_preprocess, 41 86 .answer_process = null_answer_process, 42 87 }; -
kernel/generic/src/ipc/ops/stchngath.c
r642dc72 re8039a86 34 34 35 35 #include <ipc/sysipc_ops.h> 36 #include <ipc/ipc.h> 37 #include <ipc/ipcrsc.h> 38 #include <synch/mutex.h> 39 #include <proc/task.h> 40 #include <abi/errno.h> 41 #include <macros.h> 42 43 static int request_preprocess(call_t *call, phone_t *phone) 44 { 45 phone_t *sender_phone; 46 task_t *other_task_s; 47 48 if (phone_get(IPC_GET_ARG5(call->data), &sender_phone) != EOK) 49 return ENOENT; 50 51 mutex_lock(&sender_phone->lock); 52 if (sender_phone->state != IPC_PHONE_CONNECTED) { 53 mutex_unlock(&sender_phone->lock); 54 return EINVAL; 55 } 56 57 other_task_s = sender_phone->callee->task; 58 59 mutex_unlock(&sender_phone->lock); 60 61 /* Remember the third party task hash. */ 62 IPC_SET_ARG5(call->data, (sysarg_t) other_task_s); 63 64 return EOK; 65 } 66 67 static int answer_preprocess(call_t *answer, ipc_data_t *olddata) 68 { 69 int rc = EOK; 70 71 if (!IPC_GET_RETVAL(answer->data)) { 72 /* The recipient authorized the change of state. */ 73 phone_t *recipient_phone; 74 task_t *other_task_s; 75 task_t *other_task_r; 76 77 rc = phone_get(IPC_GET_ARG1(answer->data), 78 &recipient_phone); 79 if (rc != EOK) { 80 IPC_SET_RETVAL(answer->data, ENOENT); 81 return ENOENT; 82 } 83 84 mutex_lock(&recipient_phone->lock); 85 if (recipient_phone->state != IPC_PHONE_CONNECTED) { 86 mutex_unlock(&recipient_phone->lock); 87 IPC_SET_RETVAL(answer->data, EINVAL); 88 return EINVAL; 89 } 90 91 other_task_r = recipient_phone->callee->task; 92 other_task_s = (task_t *) IPC_GET_ARG5(*olddata); 93 94 /* 95 * See if both the sender and the recipient meant the 96 * same third party task. 97 */ 98 if (other_task_r != other_task_s) { 99 IPC_SET_RETVAL(answer->data, EINVAL); 100 rc = EINVAL; 101 } else { 102 rc = event_task_notify_5(other_task_r, 103 EVENT_TASK_STATE_CHANGE, false, 104 IPC_GET_ARG1(*olddata), 105 IPC_GET_ARG2(*olddata), 106 IPC_GET_ARG3(*olddata), 107 LOWER32(olddata->task_id), 108 UPPER32(olddata->task_id)); 109 IPC_SET_RETVAL(answer->data, rc); 110 } 111 112 mutex_unlock(&recipient_phone->lock); 113 } 114 115 return rc; 116 } 36 117 37 118 sysipc_ops_t ipc_m_state_change_authorize_ops = { 38 .request_preprocess = null_request_preprocess,119 .request_preprocess = request_preprocess, 39 120 .request_process = null_request_process, 40 .answer_preprocess = null_answer_preprocess,121 .answer_preprocess = answer_preprocess, 41 122 .answer_process = null_answer_process, 42 123 }; -
kernel/generic/src/ipc/sysipc.c
r642dc72 re8039a86 34 34 35 35 #include <arch.h> 36 #include <proc/task.h>37 #include <proc/thread.h>38 36 #include <errno.h> 39 37 #include <memstr.h> 40 #include <debug.h>41 38 #include <ipc/ipc.h> 42 39 #include <abi/ipc/methods.h> 43 40 #include <ipc/sysipc.h> 41 #include <ipc/sysipc_ops.h> 44 42 #include <ipc/irq.h> 45 43 #include <ipc/ipcrsc.h> … … 47 45 #include <ipc/kbox.h> 48 46 #include <synch/waitq.h> 49 #include <udebug/udebug_ipc.h>50 47 #include <arch/interrupt.h> 51 48 #include <syscall/copy.h> 52 49 #include <security/cap.h> 53 50 #include <console/console.h> 54 #include <mm/as.h>55 51 #include <print.h> 56 52 #include <macros.h> 57 53 58 /**59 * Maximum buffer size allowed for IPC_M_DATA_WRITE and IPC_M_DATA_READ60 * requests.61 */62 #define DATA_XFER_LIMIT (64 * 1024)63 64 54 #define STRUCT_TO_USPACE(dst, src) copy_to_uspace((dst), (src), sizeof(*(src))) 65 66 /** Get phone from the current task by ID.67 *68 * @param phoneid Phone ID.69 * @param phone Place to store pointer to phone.70 *71 * @return EOK on success, EINVAL if ID is invalid.72 *73 */74 static int phone_get(sysarg_t phoneid, phone_t **phone)75 {76 if (phoneid >= IPC_MAX_PHONES)77 return EINVAL;78 79 *phone = &TASK->phones[phoneid];80 return EOK;81 }82 55 83 56 /** Decide if the interface and method is a system method. … … 174 147 } 175 148 176 static void cleanup_m_connection_clone(call_t *answer, ipc_data_t *olddata)177 {178 int phoneid = (int) IPC_GET_ARG1(*olddata);179 phone_t *phone = &TASK->phones[phoneid];180 181 /*182 * In this case, the connection was established at the request time and183 * therefore we need to slam the phone. We don't merely hangup as that184 * would result in sending IPC_M_HUNGUP to the third party on the other185 * side of the cloned phone.186 */187 mutex_lock(&phone->lock);188 if (phone->state == IPC_PHONE_CONNECTED) {189 irq_spinlock_lock(&phone->callee->lock, true);190 list_remove(&phone->link);191 phone->state = IPC_PHONE_SLAMMED;192 irq_spinlock_unlock(&phone->callee->lock, true);193 }194 mutex_unlock(&phone->lock);195 }196 197 static int a_preprocess_m_connection_clone(call_t *answer, ipc_data_t *olddata)198 {199 if (IPC_GET_RETVAL(answer->data) != EOK) {200 /*201 * The recipient of the cloned phone rejected the offer.202 */203 cleanup_m_connection_clone(answer, olddata);204 }205 206 return EOK;207 }208 209 static int a_preprocess_m_clone_establish(call_t *answer, ipc_data_t *olddata)210 {211 phone_t *phone = (phone_t *) IPC_GET_ARG5(*olddata);212 213 if (IPC_GET_RETVAL(answer->data) != EOK) {214 /*215 * The other party on the cloned phone rejected our request216 * for connection on the protocol level. We need to break the217 * connection without sending IPC_M_HUNGUP back.218 */219 mutex_lock(&phone->lock);220 if (phone->state == IPC_PHONE_CONNECTED) {221 irq_spinlock_lock(&phone->callee->lock, true);222 list_remove(&phone->link);223 phone->state = IPC_PHONE_SLAMMED;224 irq_spinlock_unlock(&phone->callee->lock, true);225 }226 mutex_unlock(&phone->lock);227 }228 229 return EOK;230 }231 232 static void cleanup_m_connect_to_me(call_t *answer, ipc_data_t *olddata)233 {234 int phoneid = (int) IPC_GET_ARG5(*olddata);235 236 phone_dealloc(phoneid);237 }238 239 static int a_preprocess_m_connect_to_me(call_t *answer, ipc_data_t *olddata)240 {241 int phoneid = (int) IPC_GET_ARG5(*olddata);242 243 if (IPC_GET_RETVAL(answer->data) != EOK) {244 /* The connection was not accepted */245 cleanup_m_connect_to_me(answer, olddata);246 } else {247 /* The connection was accepted */248 phone_connect(phoneid, &answer->sender->answerbox);249 /* Set 'phone hash' as arg5 of response */250 IPC_SET_ARG5(answer->data, (sysarg_t) &TASK->phones[phoneid]);251 }252 253 return EOK;254 }255 256 static void cleanup_m_connect_me_to(call_t *answer, ipc_data_t *olddata)257 {258 /* FIXME: answer->priv phone needs to be deallocated. */259 }260 261 static int a_preprocess_m_connect_me_to(call_t *answer, ipc_data_t *olddata)262 {263 phone_t *phone = (phone_t *) IPC_GET_ARG5(*olddata);264 265 /* If the user accepted call, connect */266 if (IPC_GET_RETVAL(answer->data) == EOK)267 ipc_phone_connect(phone, &TASK->answerbox);268 269 return EOK;270 }271 272 static int a_preprocess_m_share_out(call_t *answer, ipc_data_t *olddata)273 {274 int rc = EOK;275 276 if (!IPC_GET_RETVAL(answer->data)) {277 /* Accepted, handle as_area receipt */278 279 irq_spinlock_lock(&answer->sender->lock, true);280 as_t *as = answer->sender->as;281 irq_spinlock_unlock(&answer->sender->lock, true);282 283 uintptr_t dst_base = (uintptr_t) -1;284 rc = as_area_share(as, IPC_GET_ARG1(*olddata),285 IPC_GET_ARG2(*olddata), AS, IPC_GET_ARG3(*olddata),286 &dst_base, IPC_GET_ARG1(answer->data));287 288 if (rc == EOK) {289 rc = copy_to_uspace((void *) IPC_GET_ARG2(answer->data),290 &dst_base, sizeof(dst_base));291 }292 293 IPC_SET_RETVAL(answer->data, rc);294 }295 296 return rc;297 }298 299 static int a_preprocess_m_share_in(call_t *answer, ipc_data_t *olddata)300 {301 if (!IPC_GET_RETVAL(answer->data)) {302 irq_spinlock_lock(&answer->sender->lock, true);303 as_t *as = answer->sender->as;304 irq_spinlock_unlock(&answer->sender->lock, true);305 306 uintptr_t dst_base = (uintptr_t) -1;307 int rc = as_area_share(AS, IPC_GET_ARG1(answer->data),308 IPC_GET_ARG1(*olddata), as, IPC_GET_ARG2(answer->data),309 &dst_base, IPC_GET_ARG3(answer->data));310 IPC_SET_ARG4(answer->data, dst_base);311 IPC_SET_RETVAL(answer->data, rc);312 }313 314 return EOK;315 }316 317 static int a_preprocess_m_data_read(call_t *answer, ipc_data_t *olddata)318 {319 ASSERT(!answer->buffer);320 if (!IPC_GET_RETVAL(answer->data)) {321 /* The recipient agreed to send data. */322 uintptr_t src = IPC_GET_ARG1(answer->data);323 uintptr_t dst = IPC_GET_ARG1(*olddata);324 size_t max_size = IPC_GET_ARG2(*olddata);325 size_t size = IPC_GET_ARG2(answer->data);326 if (size && size <= max_size) {327 /*328 * Copy the destination VA so that this piece of329 * information is not lost.330 */331 IPC_SET_ARG1(answer->data, dst);332 333 answer->buffer = malloc(size, 0);334 int rc = copy_from_uspace(answer->buffer,335 (void *) src, size);336 if (rc) {337 IPC_SET_RETVAL(answer->data, rc);338 free(answer->buffer);339 answer->buffer = NULL;340 }341 } else if (!size) {342 IPC_SET_RETVAL(answer->data, EOK);343 } else {344 IPC_SET_RETVAL(answer->data, ELIMIT);345 }346 }347 348 return EOK;349 }350 351 static int a_preprocess_m_data_write(call_t *answer, ipc_data_t *olddata)352 {353 ASSERT(answer->buffer);354 if (!IPC_GET_RETVAL(answer->data)) {355 /* The recipient agreed to receive data. */356 uintptr_t dst = (uintptr_t)IPC_GET_ARG1(answer->data);357 size_t size = (size_t)IPC_GET_ARG2(answer->data);358 size_t max_size = (size_t)IPC_GET_ARG2(*olddata);359 360 if (size <= max_size) {361 int rc = copy_to_uspace((void *) dst,362 answer->buffer, size);363 if (rc)364 IPC_SET_RETVAL(answer->data, rc);365 } else {366 IPC_SET_RETVAL(answer->data, ELIMIT);367 }368 }369 free(answer->buffer);370 answer->buffer = NULL;371 372 return EOK;373 }374 375 static int376 a_preprocess_m_state_change_authorize(call_t *answer, ipc_data_t *olddata)377 {378 int rc = EOK;379 380 if (!IPC_GET_RETVAL(answer->data)) {381 /* The recipient authorized the change of state. */382 phone_t *recipient_phone;383 task_t *other_task_s;384 task_t *other_task_r;385 386 rc = phone_get(IPC_GET_ARG1(answer->data),387 &recipient_phone);388 if (rc != EOK) {389 IPC_SET_RETVAL(answer->data, ENOENT);390 return ENOENT;391 }392 393 mutex_lock(&recipient_phone->lock);394 if (recipient_phone->state != IPC_PHONE_CONNECTED) {395 mutex_unlock(&recipient_phone->lock);396 IPC_SET_RETVAL(answer->data, EINVAL);397 return EINVAL;398 }399 400 other_task_r = recipient_phone->callee->task;401 other_task_s = (task_t *) IPC_GET_ARG5(*olddata);402 403 /*404 * See if both the sender and the recipient meant the405 * same third party task.406 */407 if (other_task_r != other_task_s) {408 IPC_SET_RETVAL(answer->data, EINVAL);409 rc = EINVAL;410 } else {411 rc = event_task_notify_5(other_task_r,412 EVENT_TASK_STATE_CHANGE, false,413 IPC_GET_ARG1(*olddata),414 IPC_GET_ARG2(*olddata),415 IPC_GET_ARG3(*olddata),416 LOWER32(olddata->task_id),417 UPPER32(olddata->task_id));418 IPC_SET_RETVAL(answer->data, rc);419 }420 421 mutex_unlock(&recipient_phone->lock);422 }423 424 return rc;425 }426 427 /** Cleanup additional resources associated with the answer. */428 static void cleanup_forgotten(call_t *answer, ipc_data_t *olddata)429 {430 if (!olddata)431 return;432 433 switch (IPC_GET_IMETHOD(*olddata)) {434 case IPC_M_CONNECTION_CLONE:435 cleanup_m_connection_clone(answer, olddata);436 break;437 case IPC_M_CONNECT_TO_ME:438 cleanup_m_connect_to_me(answer, olddata);439 break;440 case IPC_M_CONNECT_ME_TO:441 cleanup_m_connect_me_to(answer, olddata);442 break;443 default:444 break;445 }446 }447 448 149 /** Interpret process answer as control information. 449 150 * … … 466 167 */ 467 168 spinlock_unlock(&answer->forget_lock); 468 cleanup_forgotten(answer, olddata);169 /* TODO: cleanup? */ 469 170 return rc; 470 171 } else { … … 496 197 } 497 198 498 switch (IPC_GET_IMETHOD(*olddata)) { 499 case IPC_M_CONNECTION_CLONE: 500 rc = a_preprocess_m_connection_clone(answer, olddata); 501 break; 502 case IPC_M_CLONE_ESTABLISH: 503 rc = a_preprocess_m_clone_establish(answer, olddata); 504 break; 505 case IPC_M_CONNECT_TO_ME: 506 rc = a_preprocess_m_connect_to_me(answer, olddata); 507 break; 508 case IPC_M_CONNECT_ME_TO: 509 rc = a_preprocess_m_connect_me_to(answer, olddata); 510 break; 511 case IPC_M_SHARE_OUT: 512 rc = a_preprocess_m_share_out(answer, olddata); 513 break; 514 case IPC_M_SHARE_IN: 515 rc = a_preprocess_m_share_in(answer, olddata); 516 break; 517 case IPC_M_DATA_READ: 518 rc = a_preprocess_m_data_read(answer, olddata); 519 break; 520 case IPC_M_DATA_WRITE: 521 rc = a_preprocess_m_data_write(answer, olddata); 522 break; 523 case IPC_M_STATE_CHANGE_AUTHORIZE: 524 rc = a_preprocess_m_state_change_authorize(answer, olddata); 525 break; 526 default: 527 break; 528 } 199 200 sysipc_ops_t *ops = sysipc_ops_get(IPC_GET_IMETHOD(*olddata)); 201 if (ops->answer_preprocess) 202 rc = ops->answer_preprocess(answer, olddata); 529 203 530 204 task_release(answer->sender); 531 205 532 206 return rc; 533 }534 535 static void phones_lock(phone_t *p1, phone_t *p2)536 {537 if (p1 < p2) {538 mutex_lock(&p1->lock);539 mutex_lock(&p2->lock);540 } else if (p1 > p2) {541 mutex_lock(&p2->lock);542 mutex_lock(&p1->lock);543 } else544 mutex_lock(&p1->lock);545 }546 547 static void phones_unlock(phone_t *p1, phone_t *p2)548 {549 mutex_unlock(&p1->lock);550 if (p1 != p2)551 mutex_unlock(&p2->lock);552 }553 554 static int r_preprocess_m_connection_clone(call_t *call, phone_t *phone)555 {556 phone_t *cloned_phone;557 558 if (phone_get(IPC_GET_ARG1(call->data), &cloned_phone) != EOK)559 return ENOENT;560 561 phones_lock(cloned_phone, phone);562 563 if ((cloned_phone->state != IPC_PHONE_CONNECTED) ||564 phone->state != IPC_PHONE_CONNECTED) {565 phones_unlock(cloned_phone, phone);566 return EINVAL;567 }568 569 /*570 * We can be pretty sure now that both tasks exist and we are571 * connected to them. As we continue to hold the phone locks,572 * we are effectively preventing them from finishing their573 * potential cleanup.574 *575 */576 int newphid = phone_alloc(phone->callee->task);577 if (newphid < 0) {578 phones_unlock(cloned_phone, phone);579 return ELIMIT;580 }581 582 ipc_phone_connect(&phone->callee->task->phones[newphid],583 cloned_phone->callee);584 phones_unlock(cloned_phone, phone);585 586 /* Set the new phone for the callee. */587 IPC_SET_ARG1(call->data, newphid);588 589 return EOK;590 }591 592 static int r_preprocess_m_clone_establish(call_t *call, phone_t *phone)593 {594 IPC_SET_ARG5(call->data, (sysarg_t) phone);595 596 return EOK;597 }598 599 static int r_preprocess_m_connect_me_to(call_t *call, phone_t *phone)600 {601 int newphid = phone_alloc(TASK);602 603 if (newphid < 0)604 return ELIMIT;605 606 /* Set arg5 for server */607 IPC_SET_ARG5(call->data, (sysarg_t) &TASK->phones[newphid]);608 call->flags |= IPC_CALL_CONN_ME_TO;609 call->priv = newphid;610 611 return EOK;612 }613 614 static int r_preprocess_m_share_out(call_t *call, phone_t *phone)615 {616 size_t size = as_area_get_size(IPC_GET_ARG1(call->data));617 618 if (!size)619 return EPERM;620 IPC_SET_ARG2(call->data, size);621 622 return EOK;623 }624 625 static int r_preprocess_m_data_read(call_t *call, phone_t *phone)626 {627 size_t size = IPC_GET_ARG2(call->data);628 629 if (size > DATA_XFER_LIMIT) {630 int flags = IPC_GET_ARG3(call->data);631 632 if (flags & IPC_XF_RESTRICT)633 IPC_SET_ARG2(call->data, DATA_XFER_LIMIT);634 else635 return ELIMIT;636 }637 638 return EOK;639 }640 641 static int r_preprocess_m_data_write(call_t *call, phone_t *phone)642 {643 uintptr_t src = IPC_GET_ARG1(call->data);644 size_t size = IPC_GET_ARG2(call->data);645 646 if (size > DATA_XFER_LIMIT) {647 int flags = IPC_GET_ARG3(call->data);648 649 if (flags & IPC_XF_RESTRICT) {650 size = DATA_XFER_LIMIT;651 IPC_SET_ARG2(call->data, size);652 } else653 return ELIMIT;654 }655 656 call->buffer = (uint8_t *) malloc(size, 0);657 int rc = copy_from_uspace(call->buffer, (void *) src, size);658 if (rc != 0) {659 free(call->buffer);660 return rc;661 }662 663 return EOK;664 }665 666 static int r_preprocess_m_state_change_authorize(call_t *call, phone_t *phone)667 {668 phone_t *sender_phone;669 task_t *other_task_s;670 671 if (phone_get(IPC_GET_ARG5(call->data), &sender_phone) != EOK)672 return ENOENT;673 674 mutex_lock(&sender_phone->lock);675 if (sender_phone->state != IPC_PHONE_CONNECTED) {676 mutex_unlock(&sender_phone->lock);677 return EINVAL;678 }679 680 other_task_s = sender_phone->callee->task;681 682 mutex_unlock(&sender_phone->lock);683 684 /* Remember the third party task hash. */685 IPC_SET_ARG5(call->data, (sysarg_t) other_task_s);686 687 return EOK;688 207 } 689 208 … … 700 219 int rc = EOK; 701 220 702 switch (IPC_GET_IMETHOD(call->data)) { 703 case IPC_M_CONNECTION_CLONE: 704 rc = r_preprocess_m_connection_clone(call, phone); 705 break; 706 case IPC_M_CLONE_ESTABLISH: 707 rc = r_preprocess_m_clone_establish(call, phone); 708 break; 709 case IPC_M_CONNECT_ME_TO: 710 rc = r_preprocess_m_connect_me_to(call, phone); 711 break; 712 case IPC_M_SHARE_OUT: 713 rc = r_preprocess_m_share_out(call, phone); 714 break; 715 case IPC_M_DATA_READ: 716 rc = r_preprocess_m_data_read(call, phone); 717 break; 718 case IPC_M_DATA_WRITE: 719 rc = r_preprocess_m_data_write(call, phone); 720 break; 721 case IPC_M_STATE_CHANGE_AUTHORIZE: 722 rc = r_preprocess_m_state_change_authorize(call, phone); 723 break; 724 #ifdef CONFIG_UDEBUG 725 case IPC_M_DEBUG: 726 rc = udebug_request_preprocess(call, phone); 727 break; 728 #endif 729 default: 730 break; 731 } 221 sysipc_ops_t *ops = sysipc_ops_get(IPC_GET_IMETHOD(call->data)); 222 if (ops->request_preprocess) 223 rc = ops->request_preprocess(call, phone); 732 224 733 225 return rc; … … 772 264 } 773 265 774 static int r_process_m_connect_to_me(answerbox_t *box, call_t *call)775 {776 int phoneid = phone_alloc(TASK);777 778 if (phoneid < 0) { /* Failed to allocate phone */779 IPC_SET_RETVAL(call->data, ELIMIT);780 ipc_answer(box, call);781 return -1;782 }783 784 IPC_SET_ARG5(call->data, phoneid);785 786 return EOK;787 }788 789 static int r_process_m_debug(answerbox_t *box, call_t *call)790 {791 return -1;792 }793 266 794 267 /** Do basic kernel processing of received call request. … … 805 278 int rc = EOK; 806 279 807 switch (IPC_GET_IMETHOD(call->data)) { 808 case IPC_M_CONNECT_TO_ME: 809 rc = r_process_m_connect_to_me(box, call); 810 break; 811 case IPC_M_DEBUG: 812 rc = r_process_m_debug(box, call); 813 break; 814 default: 815 break; 816 } 280 sysipc_ops_t *ops = sysipc_ops_get(IPC_GET_IMETHOD(call->data)); 281 if (ops->request_process) 282 rc = ops->request_process(call, box); 817 283 818 284 return rc; -
kernel/generic/src/ipc/sysipc_ops.c
r642dc72 re8039a86 91 91 sysipc_ops_t *sysipc_ops_get(sysarg_t imethod) 92 92 { 93 if (imethod < sizeof(sysipc_ops) / (sizeof(sysipc_ops_t )))93 if (imethod < sizeof(sysipc_ops) / (sizeof(sysipc_ops_t *))) 94 94 return sysipc_ops[imethod] ? sysipc_ops[imethod] : &null_ops; 95 95
Note:
See TracChangeset
for help on using the changeset viewer.