diff --git a/include/kernel/channel.h b/include/kernel/channel.h index 2cdde36..7488bd0 100644 --- a/include/kernel/channel.h +++ b/include/kernel/channel.h @@ -4,7 +4,7 @@ #include #include -struct kmsg; +struct msg; struct channel { struct object c_base; @@ -21,17 +21,19 @@ extern struct channel *channel_create(void); extern kern_status_t channel_enqueue_msg( struct channel *channel, - struct kmsg *msg); + struct msg *msg); extern kern_status_t channel_recv_msg( struct channel *channel, - struct msg *out_msg, msgid_t *out_id, + struct iovec *out_data, + size_t out_data_count, unsigned long *irq_flags); extern kern_status_t channel_reply_msg( struct channel *channel, msgid_t id, - const struct msg *resp, + const struct iovec *resp_data, + size_t resp_data_count, unsigned long *irq_flags); extern kern_status_t channel_read_msg( diff --git a/include/kernel/handle.h b/include/kernel/handle.h index 1c12aae..c9e9ddd 100644 --- a/include/kernel/handle.h +++ b/include/kernel/handle.h @@ -54,12 +54,4 @@ extern struct handle *handle_table_get_handle( struct handle_table *tab, kern_handle_t handle); -extern kern_status_t handle_list_transfer( - struct handle_table *dest, - struct handle_list *dest_list, - size_t dest_list_count, - struct handle_table *src, - const struct handle_list *src_list, - size_t src_list_count); - #endif diff --git a/include/kernel/msg.h b/include/kernel/msg.h index f1dcb37..754686e 100644 --- a/include/kernel/msg.h +++ b/include/kernel/msg.h @@ -15,7 +15,7 @@ enum kmsg_status { KMSG_REPLY_SENT, }; -struct kmsg { +struct msg { spin_lock_t msg_lock; enum kmsg_status msg_status; struct btree_node msg_node; @@ -23,8 +23,10 @@ struct kmsg { kern_status_t msg_result; struct port *msg_sender_port; struct thread *msg_sender_thread; - struct msg msg_req; - struct msg msg_resp; + const struct iovec *msg_req_data; + size_t msg_req_data_count; + struct iovec *msg_resp_data; + size_t msg_resp_data_count; }; #endif diff --git a/include/kernel/port.h b/include/kernel/port.h index c82a16d..6977612 100644 --- a/include/kernel/port.h +++ b/include/kernel/port.h @@ -32,8 +32,10 @@ extern kern_status_t port_connect(struct port *port, struct channel *remote); extern kern_status_t port_disconnect(struct port *port); extern kern_status_t port_send_msg( struct port *port, - const struct msg *req, - struct msg *resp, + const struct iovec *req_data, + size_t req_data_count, + struct iovec *resp_data, + size_t resp_data_count, unsigned long *lock_flags); DEFINE_OBJECT_LOCK_FUNCTION(port, p_base) diff --git a/include/kernel/sched.h b/include/kernel/sched.h index f2f78ac..0a44e3c 100644 --- a/include/kernel/sched.h +++ b/include/kernel/sched.h @@ -114,7 +114,7 @@ struct thread { virt_addr_t tr_cpu_user_sp, tr_cpu_kernel_sp; struct runqueue *tr_rq; - struct kmsg tr_msg; + struct msg tr_msg; struct queue_entry tr_parent_entry; struct queue_entry tr_rqentry; diff --git a/include/kernel/syscall.h b/include/kernel/syscall.h index be9e45e..7c7191d 100644 --- a/include/kernel/syscall.h +++ b/include/kernel/syscall.h @@ -2,16 +2,14 @@ #define KERNEL_SYSCALL_H_ #include +#include +#include #include #include #include #define validate_access(task, ptr, len, flags) \ - vm_region_validate_access( \ - task->t_address_space, \ - (virt_addr_t)ptr, \ - len, \ - flags | VM_PROT_USER) + __validate_access(task, (const void *)ptr, len, flags) #define validate_access_r(task, ptr, len) \ validate_access(task, ptr, len, VM_PROT_READ | VM_PROT_USER) #define validate_access_w(task, ptr, len) \ @@ -23,6 +21,23 @@ len, \ VM_PROT_READ | VM_PROT_WRITE | VM_PROT_USER) +static inline bool __validate_access( + struct task *task, + const void *ptr, + size_t len, + vm_prot_t flags) +{ + unsigned long irq_flags; + vm_region_lock_irqsave(task->t_address_space, &irq_flags); + bool result = vm_region_validate_access( + task->t_address_space, + (virt_addr_t)ptr, + len, + flags | VM_PROT_USER); + vm_region_unlock_irqrestore(task->t_address_space, irq_flags); + return result; +} + extern kern_status_t sys_task_exit(int status); extern kern_status_t sys_task_self(kern_handle_t *out); extern kern_status_t sys_task_create( @@ -128,10 +143,7 @@ extern kern_status_t sys_kern_config_set( const void *ptr, size_t len); -extern kern_status_t sys_channel_create( - unsigned int id, - channel_flags_t flags, - kern_handle_t *out); +extern kern_status_t sys_channel_create(unsigned int id, kern_handle_t *out); extern kern_status_t sys_port_create(kern_handle_t *out); extern kern_status_t sys_port_connect( kern_handle_t port, @@ -141,22 +153,20 @@ extern kern_status_t sys_port_disconnect(kern_handle_t port); extern kern_status_t sys_msg_send( kern_handle_t port, - msg_flags_t flags, - const struct msg *req, - struct msg *resp); - + const struct iovec *req_data, + size_t req_data_count, + struct iovec *resp_data, + size_t resp_data_count); extern kern_status_t sys_msg_recv( kern_handle_t channel, - msg_flags_t flags, msgid_t *out_id, - struct msg *out_msg); - + struct iovec *out_data, + size_t out_data_count); extern kern_status_t sys_msg_reply( kern_handle_t channel, - msg_flags_t flags, msgid_t id, - const struct msg *reply); - + const struct iovec *reply_data, + size_t reply_data_count); extern kern_status_t sys_msg_read( kern_handle_t channel_handle, msgid_t id, @@ -164,25 +174,13 @@ extern kern_status_t sys_msg_read( const struct iovec *iov, size_t iov_count, size_t *nr_read); -extern kern_status_t sys_msg_read_handles( - kern_handle_t channel, - msgid_t id, - size_t offset, - struct handle_list *out, - size_t nr_out); - extern kern_status_t sys_msg_write( kern_handle_t channel, msgid_t id, size_t offset, const struct iovec *in, - size_t nr_in); -extern kern_status_t sys_msg_write_handles( - kern_handle_t channel, - msgid_t id, - size_t offset, - const struct handle_list *in, - size_t nr_in); + size_t nr_in, + size_t *nr_written); extern virt_addr_t syscall_get_function(unsigned int sysid); diff --git a/kernel/channel.c b/kernel/channel.c index ce342d2..0229cc1 100644 --- a/kernel/channel.c +++ b/kernel/channel.c @@ -12,7 +12,7 @@ static struct object_type channel_type = { .ob_header_offset = offsetof(struct channel, c_base), }; -BTREE_DEFINE_SIMPLE_GET(struct kmsg, msgid_t, msg_node, msg_id, get_msg_with_id) +BTREE_DEFINE_SIMPLE_GET(struct msg, msgid_t, msg_node, msg_id, get_msg_with_id) kern_status_t channel_type_init(void) { @@ -36,7 +36,7 @@ extern struct channel *channel_create(void) return channel; } -static bool try_enqueue(struct btree *tree, struct kmsg *msg) +static bool try_enqueue(struct btree *tree, struct msg *msg) { if (!tree->b_root) { tree->b_root = &msg->msg_node; @@ -46,8 +46,8 @@ static bool try_enqueue(struct btree *tree, struct kmsg *msg) struct btree_node *cur = tree->b_root; while (1) { - struct kmsg *cur_node - = BTREE_CONTAINER(struct kmsg, msg_node, cur); + struct msg *cur_node + = BTREE_CONTAINER(struct msg, msg_node, cur); struct btree_node *next = NULL; if (msg->msg_id > cur_node->msg_id) { @@ -76,7 +76,7 @@ static bool try_enqueue(struct btree *tree, struct kmsg *msg) } static void kmsg_reply_error( - struct kmsg *msg, + struct msg *msg, kern_status_t status, unsigned long *lock_flags) { @@ -87,13 +87,13 @@ static void kmsg_reply_error( spin_unlock_irqrestore(&msg->msg_lock, *lock_flags); } -static struct kmsg *get_next_msg( +static struct msg *get_next_msg( struct channel *channel, unsigned long *lock_flags) { struct btree_node *cur = btree_first(&channel->c_msg); while (cur) { - struct kmsg *msg = BTREE_CONTAINER(struct kmsg, msg_node, cur); + struct msg *msg = BTREE_CONTAINER(struct msg, msg_node, cur); spin_lock_irqsave(&msg->msg_lock, lock_flags); if (msg->msg_status == KMSG_WAIT_RECEIVE) { msg->msg_status = KMSG_WAIT_REPLY; @@ -110,7 +110,7 @@ static struct kmsg *get_next_msg( extern kern_status_t channel_enqueue_msg( struct channel *channel, - struct kmsg *msg) + struct msg *msg) { fill_random(&msg->msg_id, sizeof msg->msg_id); while (!try_enqueue(&channel->c_msg, msg)) { @@ -124,13 +124,14 @@ extern kern_status_t channel_enqueue_msg( extern kern_status_t channel_recv_msg( struct channel *channel, - struct msg *out_msg, msgid_t *out_id, + struct iovec *out_data, + size_t out_data_count, unsigned long *irq_flags) { struct wait_item waiter; struct thread *self = current_thread(); - struct kmsg *msg = NULL; + struct msg *msg = NULL; unsigned long msg_lock_flags; wait_item_init(&waiter, self); @@ -160,12 +161,12 @@ extern kern_status_t channel_recv_msg( kern_status_t status = vm_region_memmove_v( dst, 0, - out_msg->msg_data, - out_msg->msg_data_count, + out_data, + out_data_count, src, 0, - msg->msg_req.msg_data, - msg->msg_req.msg_data_count, + msg->msg_req_data, + msg->msg_req_data_count, VM_REGION_COPY_ALL, NULL); vm_region_unlock_pair_irqrestore(src, dst, f); @@ -175,18 +176,6 @@ extern kern_status_t channel_recv_msg( return status; } - status = handle_list_transfer( - receiver->t_handles, - out_msg->msg_handles, - out_msg->msg_handles_count, - sender->t_handles, - msg->msg_req.msg_handles, - msg->msg_req.msg_handles_count); - if (status != KERN_OK) { - kmsg_reply_error(msg, status, &msg_lock_flags); - return status; - } - *out_id = msg->msg_id; spin_unlock_irqrestore(&msg->msg_lock, msg_lock_flags); @@ -197,11 +186,12 @@ extern kern_status_t channel_recv_msg( extern kern_status_t channel_reply_msg( struct channel *channel, msgid_t id, - const struct msg *resp, + const struct iovec *resp_data, + size_t resp_data_count, unsigned long *irq_flags) { unsigned long msg_lock_flags; - struct kmsg *msg = get_msg_with_id(&channel->c_msg, id); + struct msg *msg = get_msg_with_id(&channel->c_msg, id); if (!msg) { return KERN_INVALID_ARGUMENT; } @@ -226,12 +216,12 @@ extern kern_status_t channel_reply_msg( kern_status_t status = vm_region_memmove_v( dst, 0, - msg->msg_resp.msg_data, - msg->msg_resp.msg_data_count, + msg->msg_resp_data, + msg->msg_resp_data_count, src, 0, - resp->msg_data, - resp->msg_data_count, + resp_data, + resp_data_count, VM_REGION_COPY_ALL, NULL); vm_region_unlock_pair_irqrestore(src, dst, f); @@ -241,18 +231,6 @@ extern kern_status_t channel_reply_msg( return status; } - status = handle_list_transfer( - receiver->t_handles, - msg->msg_resp.msg_handles, - msg->msg_resp.msg_handles_count, - sender->t_handles, - resp->msg_handles, - resp->msg_handles_count); - if (status != KERN_OK) { - kmsg_reply_error(msg, status, &msg_lock_flags); - return status; - } - kmsg_reply_error(msg, KERN_OK, &msg_lock_flags); return KERN_OK; @@ -268,7 +246,7 @@ extern kern_status_t channel_read_msg( size_t *nr_read) { unsigned long msg_lock_flags; - struct kmsg *msg = get_msg_with_id(&channel->c_msg, id); + struct msg *msg = get_msg_with_id(&channel->c_msg, id); if (!msg) { return KERN_INVALID_ARGUMENT; } @@ -292,8 +270,8 @@ extern kern_status_t channel_read_msg( dest_iov_count, src_region, offset, - msg->msg_req.msg_data, - msg->msg_req.msg_data_count, + msg->msg_req_data, + msg->msg_req_data_count, VM_REGION_COPY_ALL, nr_read); vm_region_unlock_pair_irqrestore(src_region, dest_region, f); @@ -305,12 +283,45 @@ extern kern_status_t channel_read_msg( extern kern_status_t channel_write_msg( struct channel *channel, - msgid_t msg, + msgid_t id, size_t offset, struct vm_region *src_region, const struct iovec *src_iov, size_t src_iov_count, size_t *nr_written) { - return KERN_UNIMPLEMENTED; + unsigned long msg_lock_flags; + struct msg *msg = get_msg_with_id(&channel->c_msg, id); + if (!msg) { + return KERN_INVALID_ARGUMENT; + } + + spin_lock_irqsave(&msg->msg_lock, &msg_lock_flags); + if (msg->msg_status != KMSG_WAIT_REPLY) { + spin_unlock_irqrestore(&msg->msg_lock, msg_lock_flags); + return KERN_INVALID_ARGUMENT; + } + + struct vm_region *dest_region + = msg->msg_sender_thread->tr_parent->t_address_space; + + unsigned long f; + vm_region_lock_pair_irqsave(src_region, dest_region, &f); + + kern_status_t status = vm_region_memmove_v( + dest_region, + 0, + msg->msg_resp_data, + msg->msg_resp_data_count, + src_region, + offset, + src_iov, + src_iov_count, + VM_REGION_COPY_ALL, + nr_written); + vm_region_unlock_pair_irqrestore(src_region, dest_region, f); + + spin_unlock_irqrestore(&msg->msg_lock, msg_lock_flags); + + return status; } diff --git a/kernel/handle.c b/kernel/handle.c index e435964..d25aa7c 100644 --- a/kernel/handle.c +++ b/kernel/handle.c @@ -191,123 +191,3 @@ struct handle *handle_table_get_handle( return &tab->t_handles.t_handle_list[handle_index]; } - -struct handle_list_iterator { - struct handle_list *it_list; - size_t it_list_count; - size_t it_list_ptr; - - kern_handle_t *it_handles; - size_t it_nr_handles; -}; - -static void handle_list_iterator_begin( - struct handle_list_iterator *it, - struct handle_list *list, - size_t list_count) -{ - memset(it, 0x0, sizeof *it); - it->it_list = list; - it->it_list_count = list_count; - - while (it->it_list_ptr < list_count) { - if (list[it->it_list_ptr].l_nr_handles > 0) { - break; - } - - it->it_list_ptr++; - } - - if (it->it_list_ptr >= list_count) { - return; - } - - it->it_handles = list[it->it_list_ptr].l_handles; - it->it_nr_handles = list[it->it_list_ptr].l_nr_handles; -} - -static void handle_list_iterator_seek( - struct handle_list_iterator *it, - size_t nr_handles) -{ - if (nr_handles > it->it_nr_handles) { - nr_handles = it->it_nr_handles; - } - - if (nr_handles < it->it_nr_handles) { - it->it_handles += nr_handles; - it->it_nr_handles -= nr_handles; - return; - } - - it->it_list_ptr++; - while (it->it_list_ptr < it->it_list_count) { - if (it->it_list[it->it_list_ptr].l_nr_handles > 0) { - break; - } - - it->it_list_ptr++; - } - - if (it->it_list_ptr >= it->it_list_count) { - return; - } - - it->it_handles = it->it_list[it->it_list_ptr].l_handles; - it->it_nr_handles = it->it_list[it->it_list_ptr].l_nr_handles; -} - -kern_status_t handle_list_transfer( - struct handle_table *dest_table, - struct handle_list *dest_list, - size_t dest_list_count, - struct handle_table *src_table, - const struct handle_list *src_list, - size_t src_list_count) -{ - struct handle_list_iterator src, dest; - handle_list_iterator_begin( - &src, - (struct handle_list *)src_list, - src_list_count); - handle_list_iterator_begin(&dest, dest_list, dest_list_count); - - while (src.it_nr_handles && dest.it_nr_handles) { - size_t to_copy = MIN(src.it_nr_handles, dest.it_nr_handles); - for (size_t i = 0; i < to_copy; i++) { - kern_handle_t handle_v = src.it_handles[i]; - struct handle *handle - = handle_table_get_handle(src_table, handle_v); - if (!handle) { - return KERN_HANDLE_INVALID; - } - - struct object *obj = object_ref(handle->h_object); - handle_flags_t flags = handle->h_flags; - - handle_table_free_handle(src_table, handle_v); - - struct handle *dest_slot = NULL; - kern_status_t status = handle_table_alloc_handle( - dest_table, - &dest_slot, - &handle_v); - if (status != KERN_OK) { - return status; - } - - dest_slot->h_object = obj; - dest_slot->h_flags = flags; - - object_add_handle(obj); - object_unref(obj); - - dest.it_handles[i] = handle_v; - } - - handle_list_iterator_seek(&src, to_copy); - handle_list_iterator_seek(&dest, to_copy); - } - - return KERN_OK; -} diff --git a/kernel/port.c b/kernel/port.c index 84346e8..96742a8 100644 --- a/kernel/port.c +++ b/kernel/port.c @@ -20,7 +20,7 @@ struct port *port_cast(struct object *obj) return PORT_CAST(obj); } -static void wait_for_reply(struct kmsg *msg, unsigned long *lock_flags) +static void wait_for_reply(struct msg *msg, unsigned long *lock_flags) { struct wait_item waiter; struct thread *self = current_thread(); @@ -78,8 +78,10 @@ kern_status_t port_disconnect(struct port *port) kern_status_t port_send_msg( struct port *port, - const struct msg *req, - struct msg *resp, + const struct iovec *req_data, + size_t req_data_count, + struct iovec *resp_data, + size_t resp_data_count, unsigned long *lock_flags) { if (port->p_status != PORT_READY) { @@ -87,13 +89,15 @@ kern_status_t port_send_msg( } struct thread *self = current_thread(); - struct kmsg *msg = &self->tr_msg; + struct msg *msg = &self->tr_msg; memset(msg, 0x0, sizeof *msg); msg->msg_status = KMSG_WAIT_RECEIVE; msg->msg_sender_thread = self; msg->msg_sender_port = port; - msg->msg_req = *req; - msg->msg_resp = *resp; + msg->msg_req_data = req_data; + msg->msg_req_data_count = req_data_count; + msg->msg_resp_data = resp_data; + msg->msg_resp_data_count = resp_data_count; unsigned long flags; channel_lock_irqsave(port->p_remote, &flags); diff --git a/libmango/arch/x86_64/syscall.S b/libmango/arch/x86_64/syscall.S index a2059df..40a1850 100644 --- a/libmango/arch/x86_64/syscall.S +++ b/libmango/arch/x86_64/syscall.S @@ -82,15 +82,13 @@ SYSCALL_GATE kern_handle_close SYS_KERN_HANDLE_CLOSE 1 SYSCALL_GATE kern_config_get SYS_KERN_CONFIG_GET 3 SYSCALL_GATE kern_config_set SYS_KERN_CONFIG_SET 3 -SYSCALL_GATE channel_create SYS_CHANNEL_CREATE 3 +SYSCALL_GATE channel_create SYS_CHANNEL_CREATE 2 SYSCALL_GATE port_create SYS_PORT_CREATE 1 SYSCALL_GATE port_connect SYS_PORT_CONNECT 3 SYSCALL_GATE port_disconnect SYS_PORT_DISCONNECT 1 -SYSCALL_GATE msg_send SYS_MSG_SEND 4 +SYSCALL_GATE msg_send SYS_MSG_SEND 5 SYSCALL_GATE msg_recv SYS_MSG_RECV 4 SYSCALL_GATE msg_reply SYS_MSG_REPLY 4 -SYSCALL_GATE msg_read SYS_MSG_READ 5 -SYSCALL_GATE msg_read_handles SYS_MSG_READ_HANDLES 5 -SYSCALL_GATE msg_write SYS_MSG_WRITE 5 -SYSCALL_GATE msg_write_handles SYS_MSG_WRITE_HANDLES 5 +SYSCALL_GATE msg_read SYS_MSG_READ 6 +SYSCALL_GATE msg_write SYS_MSG_WRITE 6 diff --git a/libmango/include-user/mango/msg.h b/libmango/include-user/mango/msg.h index aaf3e96..82e5ff0 100644 --- a/libmango/include-user/mango/msg.h +++ b/libmango/include-user/mango/msg.h @@ -4,10 +4,7 @@ #include #include -extern kern_status_t channel_create( - unsigned int id, - channel_flags_t flags, - kern_handle_t *out); +extern kern_status_t channel_create(unsigned int id, kern_handle_t *out); extern kern_status_t port_create(kern_handle_t *out); extern kern_status_t port_connect( kern_handle_t port, @@ -17,21 +14,22 @@ extern kern_status_t port_disconnect(kern_handle_t port); extern kern_status_t msg_send( kern_handle_t port, - msg_flags_t flags, - const struct msg *req, - struct msg *resp); + const struct iovec *req_data, + size_t req_data_count, + struct iovec *resp_data, + size_t resp_data_count); extern kern_status_t msg_recv( kern_handle_t channel, - msg_flags_t flags, msgid_t *out_id, - struct msg *out_msg); + struct iovec *out_data, + size_t out_data_count); extern kern_status_t msg_reply( kern_handle_t channel, - msg_flags_t flags, msgid_t id, - const struct msg *reply); + const struct iovec *reply_data, + size_t reply_data_count); extern kern_status_t msg_read( kern_handle_t channel, @@ -40,24 +38,13 @@ extern kern_status_t msg_read( struct iovec *out, size_t out_count, size_t *nr_read); -extern kern_status_t msg_read_handles( - kern_handle_t channel, - msgid_t id, - size_t offset, - struct handle_list *out, - size_t nr_out); extern kern_status_t msg_write( kern_handle_t channel, msgid_t id, size_t offset, const struct iovec *in, - size_t nr_in); -extern kern_status_t msg_write_handles( - kern_handle_t channel, - msgid_t id, - size_t offset, - const struct handle_list *in, - size_t nr_in); + size_t nr_in, + size_t *nr_written); #endif diff --git a/libmango/include/mango/syscall.h b/libmango/include/mango/syscall.h index 03fd379..a59996a 100644 --- a/libmango/include/mango/syscall.h +++ b/libmango/include/mango/syscall.h @@ -27,9 +27,7 @@ #define SYS_MSG_RECV 19 #define SYS_MSG_REPLY 20 #define SYS_MSG_READ 21 -#define SYS_MSG_READ_HANDLES 22 #define SYS_MSG_WRITE 23 -#define SYS_MSG_WRITE_HANDLES 24 #define SYS_CHANNEL_CREATE 25 #define SYS_PORT_CREATE 26 #define SYS_PORT_CONNECT 27 diff --git a/libmango/include/mango/types.h b/libmango/include/mango/types.h index ee8f0b2..2d45f38 100644 --- a/libmango/include/mango/types.h +++ b/libmango/include/mango/types.h @@ -50,8 +50,6 @@ typedef unsigned int tid_t; typedef uint32_t kern_handle_t; typedef uint32_t kern_config_key_t; typedef uint32_t vm_prot_t; -typedef uint32_t channel_flags_t; -typedef uint32_t msg_flags_t; typedef unsigned int umode_t; @@ -60,17 +58,4 @@ struct iovec { size_t io_len; }; -struct handle_list { - kern_handle_t *l_handles; - size_t l_nr_handles; -}; - -struct msg { - struct iovec *msg_data; - size_t msg_data_count; - - struct handle_list *msg_handles; - size_t msg_handles_count; -}; - #endif diff --git a/syscall/dispatch.c b/syscall/dispatch.c index e714af9..40fd96b 100644 --- a/syscall/dispatch.c +++ b/syscall/dispatch.c @@ -35,9 +35,7 @@ static const virt_addr_t syscall_table[] = { SYSCALL_TABLE_ENTRY(MSG_RECV, msg_recv), SYSCALL_TABLE_ENTRY(MSG_REPLY, msg_reply), SYSCALL_TABLE_ENTRY(MSG_READ, msg_read), - SYSCALL_TABLE_ENTRY(MSG_READ_HANDLES, msg_read_handles), SYSCALL_TABLE_ENTRY(MSG_WRITE, msg_write), - SYSCALL_TABLE_ENTRY(MSG_WRITE_HANDLES, msg_write_handles), }; static const size_t syscall_table_count = sizeof syscall_table / sizeof syscall_table[0]; diff --git a/syscall/log.c b/syscall/log.c index cd88b13..328fac6 100644 --- a/syscall/log.c +++ b/syscall/log.c @@ -4,6 +4,6 @@ kern_status_t sys_kern_log(const char *s) { struct task *task = current_task(); - printk("%s: %s", task->t_name, s); + printk("%s[%d]: %s", task->t_name, task->t_id, s); return KERN_OK; } diff --git a/syscall/msg.c b/syscall/msg.c index 7070c8a..629cdcb 100644 --- a/syscall/msg.c +++ b/syscall/msg.c @@ -5,10 +5,7 @@ #include #include -kern_status_t sys_channel_create( - unsigned int id, - channel_flags_t flags, - kern_handle_t *out) +kern_status_t sys_channel_create(unsigned int id, kern_handle_t *out) { struct task *self = current_task(); if (!validate_access_w(self, out, sizeof *out)) { @@ -185,69 +182,21 @@ static bool validate_iovec( return true; } -static bool validate_msg(struct task *task, const struct msg *msg, bool rw) -{ - if (!validate_access_r(task, msg, sizeof *msg)) { - return false; - } - - if (msg->msg_data_count - && !validate_access_r( - task, - msg->msg_data, - sizeof(struct iovec) * msg->msg_data_count)) { - return false; - } - - if (msg->msg_handles_count - && !validate_access_r( - task, - msg->msg_handles, - sizeof(struct handle_list) * msg->msg_handles_count)) { - return false; - } - - if (!validate_iovec(task, msg->msg_data, msg->msg_data_count, rw)) { - return false; - } - - for (size_t i = 0; i < msg->msg_handles_count; i++) { - bool ok = false; - const struct handle_list *list = &msg->msg_handles[i]; - if (rw) { - ok = validate_access_w( - task, - list->l_handles, - list->l_nr_handles * sizeof(kern_handle_t)); - } else { - ok = validate_access_r( - task, - list->l_handles, - list->l_nr_handles * sizeof(kern_handle_t)); - } - - if (!ok) { - return false; - } - } - - return true; -} - kern_status_t sys_msg_send( kern_handle_t port_handle, - msg_flags_t msg_flags, - const struct msg *req, - struct msg *resp) + const struct iovec *req_data, + size_t req_data_count, + struct iovec *resp_data, + size_t resp_data_count) { struct task *self = current_task(); - if (!validate_msg(self, req, false)) { - return KERN_MEMORY_FAULT; + if (!validate_iovec(self, req_data, req_data_count, false)) { + return false; } - if (!validate_msg(self, resp, true)) { - return KERN_MEMORY_FAULT; + if (!validate_iovec(self, resp_data, resp_data_count, true)) { + return false; } unsigned long flags; @@ -277,7 +226,13 @@ kern_status_t sys_msg_send( } port_lock_irqsave(port, &flags); - status = port_send_msg(port, req, resp, &flags); + status = port_send_msg( + port, + req_data, + req_data_count, + resp_data, + resp_data_count, + &flags); port_unlock_irqrestore(port, flags); object_unref(port_obj); @@ -286,9 +241,9 @@ kern_status_t sys_msg_send( kern_status_t sys_msg_recv( kern_handle_t channel_handle, - msg_flags_t msg_flags, msgid_t *out_id, - struct msg *out_msg) + struct iovec *out_data, + size_t out_data_count) { struct task *self = current_task(); @@ -296,7 +251,7 @@ kern_status_t sys_msg_recv( return KERN_MEMORY_FAULT; } - if (!validate_msg(self, out_msg, true)) { + if (!validate_iovec(self, out_data, out_data_count, true)) { return KERN_MEMORY_FAULT; } @@ -327,7 +282,12 @@ kern_status_t sys_msg_recv( } channel_lock_irqsave(channel, &flags); - status = channel_recv_msg(channel, out_msg, out_id, &flags); + status = channel_recv_msg( + channel, + out_id, + out_data, + out_data_count, + &flags); channel_unlock_irqrestore(channel, flags); object_unref(channel_obj); @@ -336,13 +296,13 @@ kern_status_t sys_msg_recv( kern_status_t sys_msg_reply( kern_handle_t channel_handle, - msg_flags_t msg_flags, msgid_t id, - const struct msg *reply) + const struct iovec *reply_data, + size_t reply_data_count) { struct task *self = current_task(); - if (!validate_msg(self, reply, false)) { + if (!validate_iovec(self, reply_data, reply_data_count, false)) { return KERN_MEMORY_FAULT; } @@ -373,7 +333,12 @@ kern_status_t sys_msg_reply( } channel_lock_irqsave(channel, &flags); - status = channel_reply_msg(channel, id, reply, &flags); + status = channel_reply_msg( + channel, + id, + reply_data, + reply_data_count, + &flags); channel_unlock_irqrestore(channel, flags); object_unref(channel_obj); @@ -390,6 +355,14 @@ kern_status_t sys_msg_read( { struct task *self = current_task(); + if (nr_read && !validate_access_w(self, nr_read, sizeof *nr_read)) { + return KERN_MEMORY_FAULT; + } + + if (!validate_iovec(self, iov, iov_count, true)) { + return KERN_MEMORY_FAULT; + } + unsigned long flags; task_lock_irqsave(self, &flags); @@ -431,32 +404,62 @@ kern_status_t sys_msg_read( return status; } -kern_status_t sys_msg_read_handles( - kern_handle_t channel, - msgid_t id, - size_t offset, - struct handle_list *out, - size_t nr_out) -{ - return KERN_UNIMPLEMENTED; -} - kern_status_t sys_msg_write( - kern_handle_t channel, + kern_handle_t channel_handle, msgid_t id, size_t offset, - const struct iovec *in, - size_t nr_in) + const struct iovec *iov, + size_t iov_count, + size_t *nr_written) { - return KERN_UNIMPLEMENTED; -} + struct task *self = current_task(); -kern_status_t sys_msg_write_handles( - kern_handle_t channel, - msgid_t id, - size_t offset, - const struct handle_list *in, - size_t nr_in) -{ - return KERN_UNIMPLEMENTED; + if (nr_written + && !validate_access_w(self, nr_written, sizeof *nr_written)) { + return KERN_MEMORY_FAULT; + } + + if (!validate_iovec(self, iov, iov_count, false)) { + return KERN_MEMORY_FAULT; + } + + unsigned long flags; + + task_lock_irqsave(self, &flags); + + struct object *channel_obj = NULL; + handle_flags_t channel_handle_flags = 0; + kern_status_t status = task_resolve_handle( + self, + channel_handle, + &channel_obj, + &channel_handle_flags); + if (status != KERN_OK) { + return status; + } + + /* add a reference to the port object to make sure it isn't deleted + * while we're using it */ + object_ref(channel_obj); + task_unlock_irqrestore(self, flags); + + struct channel *channel = channel_cast(channel_obj); + if (!channel) { + object_unref(channel_obj); + return KERN_INVALID_ARGUMENT; + } + + channel_lock_irqsave(channel, &flags); + status = channel_write_msg( + channel, + id, + offset, + self->t_address_space, + iov, + iov_count, + nr_written); + channel_unlock_irqrestore(channel, flags); + object_unref(channel_obj); + + return status; } diff --git a/syscall/task.c b/syscall/task.c index daa9c61..444423e 100644 --- a/syscall/task.c +++ b/syscall/task.c @@ -6,9 +6,10 @@ extern kern_status_t sys_task_exit(int status) { + struct task *self = current_task(); + printk("%s[%d]: task_exit(%d)", self->t_name, self->t_id, status); while (1) { - printk("sys_exit(%d)", status); - milli_sleep(1000); + milli_sleep(5000); } return KERN_UNIMPLEMENTED;