From 70d5ff33cd1662e10705ffbaa503e39a822efea3 Mon Sep 17 00:00:00 2001 From: Bahadir Balban Date: Mon, 4 Feb 2008 21:03:51 +0000 Subject: [PATCH] This patch adds ipc_sendrecv() and opens the way for client/server communication. ipc_sendrecv() replaces ipc_sendwait() which was flawed. See ipc_sendrecv() for how client/server communication works. Tested with page faults where the kernel does an ipc_sendrecv() to faulty thread's pager and the pager successfully handles the request, and returns back the result, which effectively restarts the faulty thread. --- include/l4/api/ipc.h | 3 ++- loader/start.axf.S | 16 ---------------- src/api/ipc.c | 29 ++++++++++++++++------------- src/arch/arm/exception.c | 2 +- tasks/mm0/src/fault.c | 13 ++++++++++--- 5 files changed, 29 insertions(+), 34 deletions(-) delete mode 100644 loader/start.axf.S diff --git a/include/l4/api/ipc.h b/include/l4/api/ipc.h index c62f893..9b75fa3 100644 --- a/include/l4/api/ipc.h +++ b/include/l4/api/ipc.h @@ -16,7 +16,8 @@ #if defined (__KERNEL__) /* These are kernel internal calls */ /* A helper call for sys_ipc() or internally created ipc paths. */ -int ipc_send(l4id_t tid); +int ipc_send(l4id_t to); +int ipc_sendrecv(l4id_t to, l4id_t from); /* * This version sends an extra wait ipc to its receiver so that diff --git a/loader/start.axf.S b/loader/start.axf.S deleted file mode 100644 index 964cb9d..0000000 --- a/loader/start.axf.S +++ /dev/null @@ -1,16 +0,0 @@ - -/* - * loader/start.axf.S autogenerated from build/start.axf - * - * This file is included by the loader sources so that any - * kernel symbol address can be known in advance and stopped - * at by debuggers before virtual memory is enabled. - */ - - -.section .text -.align 4 -.global break_virtual; -.type break_virtual, function; -.equ break_virtual, 0x106f9c - diff --git a/src/api/ipc.c b/src/api/ipc.c index 5870085..79e45a1 100644 --- a/src/api/ipc.c +++ b/src/api/ipc.c @@ -154,28 +154,31 @@ int ipc_sendwait(l4id_t to) } /* - * We currently only support send-receiving from the same task. The receive - * stage is initiated with the special L4_IPC_TAG_IPCRETURN. This tag is used by - * client tasks for receiving returned ipc results back. This is by far the most - * common ipc pattern between client tasks and servers since every such ipc - * request expects a result. + * Both sends and receives mregs in the same call. This is mainly by user + * tasks for client server communication with system servers. + * + * Timeline of client/server communication using ipc_sendrecv(): + * + * (1) User task (client) calls ipc_sendrecv(); + * (2) System task (server) calls ipc_recv() with from == ANYTHREAD. + * (3) Rendezvous occurs. Both tasks exchange mrs and leave rendezvous. + * (4,5) User task, immediately calls ipc_recv(), expecting a reply from server. + * (4,5) System task handles the request in userspace. + * (6) System task calls ipc_send() sending the return result. + * (7) Rendezvous occurs. Both tasks exchange mrs and leave rendezvous. */ int ipc_sendrecv(l4id_t to, l4id_t from) { int ret = 0; if (to == from) { - - /* IPC send request stage */ + /* Send ipc request */ ipc_send(to); /* - * IPC result return stage. - * - * If the receiving task is scheduled here, (likely to be a - * server which shouldn't block too long) it would only block - * for a fixed amount of time between these send and receive - * calls. + * Get reply. + * A client would block its server only very briefly + * between these calls. */ ipc_recv(from); } else { diff --git a/src/arch/arm/exception.c b/src/arch/arm/exception.c index e4e290a..a00cb68 100644 --- a/src/arch/arm/exception.c +++ b/src/arch/arm/exception.c @@ -59,7 +59,7 @@ void fault_ipc_to_pager(u32 faulty_pc, u32 fsr, u32 far) offsetof(syscall_args_t, r3)); /* Send ipc to the task's pager */ - ipc_sendwait(current->pagerid); + ipc_sendrecv(current->pagerid, current->pagerid); /* * Pager is now notified and handling the fault. We now sleep on diff --git a/tasks/mm0/src/fault.c b/tasks/mm0/src/fault.c index d746b45..e0c95fa 100644 --- a/tasks/mm0/src/fault.c +++ b/tasks/mm0/src/fault.c @@ -368,10 +368,11 @@ int do_anon_page(struct fault_data *fault) * - page needs write access: * action: read the page in, give write access. */ -void do_page_fault(struct fault_data *fault) +int do_page_fault(struct fault_data *fault) { unsigned int vma_flags = (fault->vma) ? fault->vma->flags : VM_NONE; unsigned int reason = fault->reason; + int err; /* vma flags show no access */ if (vma_flags & VM_NONE) { @@ -394,9 +395,15 @@ void do_page_fault(struct fault_data *fault) /* Handle legitimate read faults on the vma */ if (vma_flags & VMA_ANON) - do_anon_page(fault); + err = do_anon_page(fault); else - do_file_page(fault); + err = do_file_page(fault); + + /* Return the ipc and by doing so restart the faulty thread */ + printf("Finished handling fault. Restarting thread by returning.\n"); + + l4_ipc_return(err); + return 0; } void vm_file_pager_read_page(struct fault_data *fault, void *dest_page)