Jan Kiszka wrote: > Hi all, > > this is a first attempt to add the requested mmap functionality to the > RTDM driver API.
... and this version is even more useful than the previous one (now with EXPORT_SYMBOL!). Be warned: I just compiled it, I count on third-party testers. Jan
Index: include/rtdm/rtdm_driver.h =================================================================== --- include/rtdm/rtdm_driver.h (Revision 556) +++ include/rtdm/rtdm_driver.h (Arbeitskopie) @@ -995,6 +995,10 @@ xnfree(ptr); } +int rtdm_mmap_to_user(rtdm_user_info_t *user_info, void *src_addr, size_t len, + int prot, void **pptr); +int rtdm_munmap(rtdm_user_info_t *user_info, void *ptr, size_t len); + static inline int rtdm_read_user_ok(rtdm_user_info_t *user_info, const void __user *ptr, size_t size) { Index: ksrc/skins/rtdm/drvlib.c =================================================================== --- ksrc/skins/rtdm/drvlib.c (Revision 556) +++ ksrc/skins/rtdm/drvlib.c (Arbeitskopie) @@ -31,7 +31,9 @@ #include <linux/delay.h> +#include <linux/mman.h> +#define XENO_HEAP_MODULE #include <rtdm/rtdm_driver.h> @@ -1286,7 +1288,7 @@ * Rescheduling: never. */ int rtdm_irq_disable(rtdm_irq_t *irq_handle); -/** @} */ +/** @} Interrupt Management Services */ /*! @@ -1358,16 +1360,133 @@ * environments. */ void rtdm_nrtsig_pend(rtdm_nrtsig_t *nrt_sig); -/** @} */ +/** @} Non-Real-Time Signalling Services */ +#endif /* DOXYGEN_CPP */ + /*! * @ingroup driverapi * @defgroup util Utility Services * @{ */ +static int rtdm_mmap_buffer(struct file *filp, struct vm_area_struct *vma) +{ + return xnarch_remap_page_range(vma, vma->vm_start, + virt_to_phys(filp->private_data), + vma->vm_end - vma->vm_start, PAGE_SHARED); +} + +static struct file_operations rtdm_mmap_fops = { + .mmap = rtdm_mmap_buffer, +}; + /** + * Map a kernel memory range into the address space of the user. + * + * @param[in] user_info User information pointer as passed to the invoked + * device operation handler + * @param[in] src_addr Kernel address to be mapped + * @param[in] len Length of the memory range + * @param[in] prot Protection flags for the user's memory range, typically + * either PROT_READ or PROT_READ|PROT_WRITE + * @param[in,out] pptr Address of a pointer containing the desired user + * address or NULL on entry and the finally assigned address on return + * + * @return 0 on success, otherwise: + * + * - -EXXX is returned if . + * + * @note An RTDM driver is expected to invoke rtdm_munmap on every mapped + * memory range either when the user requests it explicitly or when the + * related device is closed. + * + * Environments: + * + * This service can be called from: + * + * - Kernel module initialization/cleanup code + * - User-space task (non-RT) + * + * Rescheduling: possible. + */ +int rtdm_mmap_to_user(rtdm_user_info_t *user_info, void *src_addr, size_t len, + int prot, void **pptr) +{ + struct file *filp; + struct file_operations *old_fops; + void *old_priv_data; + void *user_ptr; + + filp = filp_open("/dev/zero", O_RDWR, 0); + if (IS_ERR(filp)) + return PTR_ERR(filp); + + old_fops = filp->f_op; + filp->f_op = &rtdm_mmap_fops; + + old_priv_data = filp->private_data; + filp->private_data = src_addr; + + down_write(&user_info->mm->mmap_sem); + user_ptr = (void *)do_mmap(filp, (unsigned long)*pptr, len, prot, + MAP_SHARED, 0); + up_write(&user_info->mm->mmap_sem); + + filp->f_op = old_fops; + filp->private_data = old_priv_data; + + filp_close(filp, user_info->files); + + if (IS_ERR(user_ptr)) + return PTR_ERR(user_ptr); + + *pptr = user_ptr; + return 0; +} + +EXPORT_SYMBOL(rtdm_mmap_to_user); + + +/** + * Unmap a user memory range. + * + * @param[in] user_info User information pointer as passed to + * rtdm_mmap_to_user() when requesting to map the memory range + * @param[in] ptr User address or the memory range + * @param[in] len Length of the memory range + * + * @return 0 on success, otherwise: + * + * - -EXXX is returned if . + * + * Environments: + * + * This service can be called from: + * + * - Kernel module initialization/cleanup code + * - User-space task (non-RT) + * + * Rescheduling: possible. + */ +int rtdm_munmap(rtdm_user_info_t *user_info, void *ptr, size_t len) +{ + int err; + + down_write(&user_info->mm->mmap_sem); + err = do_munmap(user_info->mm, (unsigned long)ptr, len); + up_write(&user_info->mm->mmap_sem); + + return err; +} + +EXPORT_SYMBOL(rtdm_munmap); + + +#ifdef DOXYGEN_CPP /* Only used for doxygen doc generation */ + +/** * Real-time safe message printing on kernel console * * @param[in] format Format string (conforming standard @c printf()) @@ -1583,6 +1702,6 @@ */ int rtdm_in_rt_context(void); -/** @} */ +#endif /* DOXYGEN_CPP */ -#endif /* DOXYGEN_CPP */ +/** @} Utility Services */
signature.asc
Description: OpenPGP digital signature