From 72c6ca1ed0b5a7be535c89f0715dd837a5fdf2f4 Mon Sep 17 00:00:00 2001 From: Bahadir Balban Date: Thu, 8 Oct 2009 15:35:54 +0300 Subject: [PATCH] Added an extended ipc return library function. --- conts/libl4/include/l4lib/arch-arm/syslib.h | 69 +++++++++++++++------ conts/posix/libposix/chdir.c | 2 - conts/posix/libposix/mkdir.c | 3 +- conts/posix/libposix/read.c | 35 ++++++++++- conts/posix/mm0/include/syscalls.h | 2 +- conts/posix/mm0/main.c | 22 ++++--- conts/posix/mm0/mm/file.c | 11 +++- include/l4/glue/arm/message.h | 2 +- src/api/ipc.c | 2 + 9 files changed, 112 insertions(+), 36 deletions(-) diff --git a/conts/libl4/include/l4lib/arch-arm/syslib.h b/conts/libl4/include/l4lib/arch-arm/syslib.h index cfba52a..dc52b7a 100644 --- a/conts/libl4/include/l4lib/arch-arm/syslib.h +++ b/conts/libl4/include/l4lib/arch-arm/syslib.h @@ -110,6 +110,23 @@ static inline void l4_set_tag(unsigned int tag) write_mr(MR_TAG, tag_flags); } +/* Servers: + * Sets the message register for returning errors back to client task. + * These are usually posix error codes. + */ +static inline void l4_set_retval(int retval) +{ + write_mr(MR_RETURN, retval); +} + +/* Clients: + * Learn result of request. + */ +static inline int l4_get_retval(void) +{ + return read_mr(MR_RETURN); +} + /* * If we're about to do another ipc, this saves the last ipc's * parameters such as the sender and tag information. @@ -195,6 +212,39 @@ static inline int l4_receive_extended(l4id_t from, unsigned int size, void *buf) return l4_ipc(L4_NILTHREAD, from, flags); } +/* + * Return result value as extended IPC. + * + * Extended IPC copies up to 2KB user address space buffers. + * Along with such an ipc, a return value is sent using a primary + * mr that is used as the return register. + * + * It may not be desirable to return a payload on certain conditions, + * (such as an error return value) So a nopayload field is provided. + */ +static inline int l4_return_extended(int retval, unsigned int size, + void *buf, int nopayload) +{ + unsigned int flags = 0; + l4id_t sender = l4_get_sender(); + + l4_set_retval(retval); + + /* Set up flags word for extended ipc */ + flags = l4_set_ipc_flags(flags, L4_IPC_FLAGS_EXTENDED); + flags = l4_set_ipc_msg_index(flags, L4SYS_ARG0); + + /* Write buffer pointer to MR index that we specified */ + write_mr(L4SYS_ARG0, (unsigned long)buf); + + if (nopayload) + flags = l4_set_ipc_size(flags, 0); + else + flags = l4_set_ipc_size(flags, size); + + return l4_ipc(sender, L4_NILTHREAD, flags); +} + static inline int l4_sendrecv_extended(l4id_t to, l4id_t from, unsigned int tag, void *buf) { @@ -226,23 +276,6 @@ static inline int l4_receive(l4id_t from) return l4_ipc(L4_NILTHREAD, from, 0); } -/* Servers: - * Sets the message register for returning errors back to client task. - * These are usually posix error codes. - */ -static inline void l4_set_retval(int retval) -{ - write_mr(MR_RETURN, retval); -} - -/* Clients: - * Learn result of request. - */ -static inline int l4_get_retval(void) -{ - return read_mr(MR_RETURN); -} - static inline void l4_print_mrs() { printf("Message registers: 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n", @@ -259,7 +292,7 @@ static inline int l4_ipc_return(int retval) l4_set_retval(retval); - /* Setting the tag may overwrite retval so we l4_send without tagging */ + /* Setting the tag would overwrite retval so we l4_send without tagging */ return l4_ipc(sender, L4_NILTHREAD, 0); } diff --git a/conts/posix/libposix/chdir.c b/conts/posix/libposix/chdir.c index 77b8dad..dd3aa5f 100644 --- a/conts/posix/libposix/chdir.c +++ b/conts/posix/libposix/chdir.c @@ -24,8 +24,6 @@ static inline int l4_chdir(const char *pathname) utcb_full_strcpy_from(pathname); - write_mr(L4SYS_ARG0, (unsigned long)utcb_full_buffer()); - /* Call pager with shmget() request. Check ipc error. */ if ((fd = l4_sendrecv_full(VFS_TID, VFS_TID, L4_IPC_TAG_CHDIR)) < 0) { print_err("%s: L4 IPC Error: %d.\n", __FUNCTION__, fd); diff --git a/conts/posix/libposix/mkdir.c b/conts/posix/libposix/mkdir.c index 856ca62..5d5f762 100644 --- a/conts/posix/libposix/mkdir.c +++ b/conts/posix/libposix/mkdir.c @@ -26,8 +26,7 @@ static inline int l4_mkdir(const char *pathname, mode_t mode) // write_mr(L4SYS_ARG0, (unsigned long)pathname); utcb_full_strcpy_from(pathname); - write_mr(L4SYS_ARG0, (unsigned long)utcb_full_buffer()); - write_mr(L4SYS_ARG1, (u32)mode); + write_mr(L4SYS_ARG0, (u32)mode); /* Call pager with shmget() request. Check ipc error. */ if ((fd = l4_sendrecv_full(PAGER_TID, PAGER_TID, L4_IPC_TAG_MKDIR)) < 0) { diff --git a/conts/posix/libposix/read.c b/conts/posix/libposix/read.c index dfe37f1..0546dc7 100644 --- a/conts/posix/libposix/read.c +++ b/conts/posix/libposix/read.c @@ -15,7 +15,7 @@ #include #include #include INC_GLUE(memory.h) -#include +#include INC_GLUE(message.h) #include /* @@ -29,6 +29,37 @@ * Or do it just like read() */ static inline int l4_readdir(int fd, void *buf, size_t count) +{ + int cnt, err; + + write_mr(L4SYS_ARG0, fd); + write_mr(L4SYS_ARG1, count); + + /* Call pager with readdir() request. Check ipc error. */ + if ((err = l4_send(PAGER_TID, L4_IPC_TAG_READDIR)) < 0) { + print_err("%s: L4 IPC Error: %d.\n", __FUNCTION__, err); + return err; + } + + /* Call pager with readdir() request. Check ipc error. */ + if ((err = l4_receive_extended(PAGER_TID, + L4_IPC_EXTENDED_MAX_SIZE, + buf)) < 0) { + print_err("%s: L4 Extended IPC error: %d.\n", __FUNCTION__, err); + return err; + } + + /* Check if syscall itself was successful */ + if ((cnt = l4_get_retval()) < 0) { + print_err("%s: READDIR Error: %d.\n", __FUNCTION__, (int)cnt); + return cnt; + } + + return cnt; +} + +#if 0 +static inline int l4_readdir(int fd, void *buf, size_t count) { int cnt; @@ -50,7 +81,7 @@ static inline int l4_readdir(int fd, void *buf, size_t count) return cnt; } - +#endif static inline int l4_read(int fd, void *buf, size_t count) { int cnt; diff --git a/conts/posix/mm0/include/syscalls.h b/conts/posix/mm0/include/syscalls.h index 32763b1..a17b200 100644 --- a/conts/posix/mm0/include/syscalls.h +++ b/conts/posix/mm0/include/syscalls.h @@ -38,7 +38,7 @@ void sys_exit(struct tcb *task, int status); /* Posix calls */ int sys_open(struct tcb *sender, const char *pathname, int flags, u32 mode); -int sys_readdir(struct tcb *sender, int fd, void *buf, int count); +int sys_readdir(struct tcb *sender, int fd, int count, char *dirbuf); int sys_mkdir(struct tcb *sender, const char *pathname, unsigned int mode); int sys_chdir(struct tcb *sender, const char *pathname); diff --git a/conts/posix/mm0/main.c b/conts/posix/mm0/main.c index 0939f89..c123081 100644 --- a/conts/posix/mm0/main.c +++ b/conts/posix/mm0/main.c @@ -148,26 +148,32 @@ void handle_requests(void) ret = sys_execve(sender, (char *)mr[0], (char **)mr[1], (char **)mr[2]); if (ret < 0) - break; /* We origy for errors */ + break; /* We reply for errors */ else return; /* else we're done */ } - /* FIXME: Fix all these syscalls to read any buffer data from the caller task's utcb. */ + /* + * FIXME: Fix all these syscalls to read any + * buffer data from the caller task's utcb. + */ + /* FS0 System calls */ case L4_IPC_TAG_OPEN: ret = sys_open(sender, utcb_full_buffer(), (int)mr[0], (unsigned int)mr[1]); break; case L4_IPC_TAG_MKDIR: - ret = sys_mkdir(sender, (const char *)mr[0], (unsigned int)mr[1]); + ret = sys_mkdir(sender, utcb_full_buffer(), (unsigned int)mr[0]); break; case L4_IPC_TAG_CHDIR: - ret = sys_chdir(sender, (const char *)mr[0]); + ret = sys_chdir(sender, utcb_full_buffer()); break; - case L4_IPC_TAG_READDIR: - ret = sys_readdir(sender, (int)mr[0], (void *)mr[1], (int)mr[2]); - break; - + case L4_IPC_TAG_READDIR: { + char dirbuf[L4_IPC_EXTENDED_MAX_SIZE]; + ret = sys_readdir(sender, (int)mr[0], (int)mr[1], dirbuf); + l4_return_extended(ret, L4_IPC_EXTENDED_MAX_SIZE, dirbuf, ret < 0); + return; + } default: printf("%s: Unrecognised ipc tag (%d) " "received from (%d). Full mr reading: " diff --git a/conts/posix/mm0/mm/file.c b/conts/posix/mm0/mm/file.c index b8b6cfe..15bdd50 100644 --- a/conts/posix/mm0/mm/file.c +++ b/conts/posix/mm0/mm/file.c @@ -31,6 +31,8 @@ #include #include +#include INC_GLUE(message.h) + /* Copy from one page's buffer into another page */ int page_copy(struct page *dst, struct page *src, unsigned long dst_offset, unsigned long src_offset, @@ -1173,17 +1175,22 @@ int fill_dirent(void *buf, unsigned long vnum, int offset, char *name) * * FIXME: Ensure buf is in shared utcb, and count does not exceed it. */ -int sys_readdir(struct tcb *t, int fd, void *buf, int count) +int sys_readdir(struct tcb *t, int fd, int count, char *dirbuf) { int dirent_size = sizeof(struct dirent); int total = 0, nbytes = 0; unsigned long vnum; struct vnode *v; struct dentry *d; + char *buf = dirbuf; // printf("%s/%s\n", __TASKNAME__, __FUNCTION__); - BUG(); /* Do this by extended ipc !!! */ + /* + * FIXME: + * Add dirbuf overflow checking + */ + /* Check address is in task's utcb */ if (fd < 0 || fd > TASK_FILES_MAX || !t->files->fd[fd].vnum) diff --git a/include/l4/glue/arm/message.h b/include/l4/glue/arm/message.h index 24210f6..bd21938 100644 --- a/include/l4/glue/arm/message.h +++ b/include/l4/glue/arm/message.h @@ -85,7 +85,7 @@ #define L4_IPC_EXTENDED_MAX_SIZE (SZ_1K*2) /* Primaries aren't used for memcopy. Those ops use this as a parameter */ -#define L4_UTCB_FULL_BUFFER_SIZE (MR_REST * sizeof(int)) +#define L4_UTCB_FULL_BUFFER_SIZE (MR_REST * sizeof(int)) #include INC_GLUE(memlayout.h) diff --git a/src/api/ipc.c b/src/api/ipc.c index c1bbfb9..4139cd1 100644 --- a/src/api/ipc.c +++ b/src/api/ipc.c @@ -131,6 +131,8 @@ int ipc_msg_copy(struct ktcb *to, struct ktcb *from) break; case IPC_FLAGS_EXTENDED: if (send_ipc_type == IPC_FLAGS_EXTENDED) + /* We do a short copy as well. */ + ret = ipc_short_copy(to, from); ret = ipc_extended_copy(to, from); if (send_ipc_type == IPC_FLAGS_SHORT) ret = -ENOIPC;