/* * Helper functions that wrap raw l4 syscalls. * * Copyright (C) 2007 Bahadir Balban */ #ifndef __L4LIB_SYSLIB_H__ #define __L4LIB_SYSLIB_H__ #include #include #include /* * NOTE: * Its best to use these wrappers because they generalise the way * common ipc data like sender id, error, ipc tag are passed * between ipc parties. * * The arguments to l4_ipc() are used by the microkernel to initiate * the ipc. Any data passed in message registers may or may not be * a duplicate of this data, but the distinction is that anything * that is passed via the mrs are meant to be used by the other party * participating in the ipc. */ /* For system call arguments */ #define L4SYS_ARG0 (MR_UNUSED_START) #define L4SYS_ARG1 (MR_UNUSED_START + 1) #define L4SYS_ARG2 (MR_UNUSED_START + 2) #define L4SYS_ARG3 (MR_UNUSED_START + 3) /* * Servers get sender. */ static inline l4id_t l4_get_sender(void) { return (l4id_t)read_mr(MR_SENDER); } /* * When doing an ipc the sender never has to be explicitly set in * the utcb via this function since it is passed in the argument * registers. This is only used for restoring the sender on the * utcb in order to complete an earlier ipc. */ static inline void l4_set_sender(l4id_t sender) { write_mr(MR_SENDER, sender); } static inline unsigned int l4_get_tag(void) { return read_mr(MR_TAG); } static inline void l4_set_tag(unsigned int tag) { write_mr(MR_TAG, tag); } /* * If we're about to do another ipc, this saves the last ipc's * parameters such as the sender and tag information. * Any previously saved data in save slots are destroyed. */ static inline void l4_save_ipcregs(void) { l4_get_utcb()->saved_sender = l4_get_sender(); l4_get_utcb()->saved_tag = l4_get_tag(); } static inline void l4_restore_ipcregs(void) { l4_set_tag(l4_get_utcb()->saved_tag); l4_set_sender(l4_get_utcb()->saved_sender); } static inline l4id_t self_tid(void) { struct task_ids ids; l4_getid(&ids); return ids.tid; } static inline int l4_send(l4id_t to, unsigned int tag) { l4_set_tag(tag); return l4_ipc(to, L4_NILTHREAD); } static inline int l4_sendrecv(l4id_t to, l4id_t from, unsigned int tag) { int err; BUG_ON(to == L4_NILTHREAD || from == L4_NILTHREAD); l4_set_tag(tag); err = l4_ipc(to, from); return err; } static inline int l4_receive(l4id_t from) { return l4_ipc(L4_NILTHREAD, from); } /* 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", read_mr(0), read_mr(1), read_mr(2), read_mr(3), read_mr(4), read_mr(5)); } /* Servers: * Return the ipc result back to requesting task. */ static inline int l4_ipc_return(int retval) { // unsigned int tag = l4_get_tag(); l4id_t sender = l4_get_sender(); l4_set_retval(retval); /* Setting the tag may overwrite retval so we l4_send without tagging */ return l4_ipc(sender, L4_NILTHREAD); } /* A helper that translates and maps a physical address to virtual */ static inline void *l4_map_helper(void *phys, int npages) { struct task_ids ids; l4_getid(&ids); l4_map(phys, phys_to_virt(phys), npages, MAP_USR_RW_FLAGS, ids.tid); return phys_to_virt(phys); } /* A helper that translates and maps a physical address to virtual */ static inline void *l4_unmap_helper(void *virt, int npages) { struct task_ids ids; l4_getid(&ids); l4_unmap(virt, npages, ids.tid); return virt_to_phys(virt); } #endif /* __L4LIB_SYSLIB_H__ */