* [Xenomai-core] [PATCH, RFC] Make ioremap'ed memory available through rtdm_mmap_to_user()
@ 2006-09-15 16:26 Stelian Pop
2006-09-15 16:40 ` Jan Kiszka
0 siblings, 1 reply; 9+ messages in thread
From: Stelian Pop @ 2006-09-15 16:26 UTC (permalink / raw)
To: xenomai
Hi,
I need to be able to map an IO memory buffer to userspace from a RTDM
driver.
rtdm_mmap_to_user() seems to do what I need, but it doesn't work. Its
code thinks that all virtual addresses between VMALLOC_START and
VMALLOC_END are obtained through vmalloc() and tries to call
xnarch_remap_vm_page() on them, which fails.
Virtual addresses coming from ioremap() need to go through
xnarch_remap_io_page_range(), and their physical address cannot be
obtained with a simple virt_to_phys().
A working patch is attached below, but there might (should ?) be a
better way to do it. Some of the code may also belong to
asm-generic/system.h instead of the RTDM skin.
Note that you may also need to EXPORT_SYMBOL(vmlist and vmlist_lock) in
mm/vmalloc.c if you want to build the RTDM skin as a module.
Comments ?
Stelian.
Index: ksrc/skins/rtdm/drvlib.c
===================================================================
--- ksrc/skins/rtdm/drvlib.c (révision 1624)
+++ ksrc/skins/rtdm/drvlib.c (copie de travail)
@@ -1377,6 +1377,7 @@
{
struct rtdm_mmap_data *mmap_data = filp->private_data;
unsigned long vaddr, maddr, size;
+ struct vm_struct *vm;
vma->vm_ops = mmap_data->vm_ops;
vma->vm_private_data = mmap_data->vm_private_data;
@@ -1385,7 +1386,21 @@
maddr = vma->vm_start;
size = vma->vm_end - vma->vm_start;
+ write_lock(&vmlist_lock);
+ for (vm = vmlist; vm != NULL; vm = vm->next) {
+ if (vm->addr == (void *)vaddr)
+ break;
+ }
+ write_unlock(&vmlist_lock);
+
+ /* ioremap'ed memory */
+ if (vm && vm->flags & VM_IOREMAP)
+ return xnarch_remap_io_page_range(vma, maddr,
+ vm->phys_addr,
+ size, PAGE_SHARED);
+ else
#ifdef CONFIG_MMU
+ /* vmalloc'ed memory */
if ((vaddr >= VMALLOC_START) && (vaddr < VMALLOC_END)) {
unsigned long mapped_size = 0;
--
Stelian Pop <stelian.pop@domain.hid>
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [Xenomai-core] [PATCH, RFC] Make ioremap'ed memory available through rtdm_mmap_to_user() 2006-09-15 16:26 [Xenomai-core] [PATCH, RFC] Make ioremap'ed memory available through rtdm_mmap_to_user() Stelian Pop @ 2006-09-15 16:40 ` Jan Kiszka 2006-09-18 21:13 ` Stelian Pop 0 siblings, 1 reply; 9+ messages in thread From: Jan Kiszka @ 2006-09-15 16:40 UTC (permalink / raw) To: Stelian Pop; +Cc: xenomai [-- Attachment #1: Type: text/plain, Size: 1410 bytes --] Stelian Pop wrote: > Hi, > > I need to be able to map an IO memory buffer to userspace from a RTDM > driver. > > rtdm_mmap_to_user() seems to do what I need, but it doesn't work. Its > code thinks that all virtual addresses between VMALLOC_START and > VMALLOC_END are obtained through vmalloc() and tries to call > xnarch_remap_vm_page() on them, which fails. Ok, interesting (one never stops learning). > > Virtual addresses coming from ioremap() need to go through > xnarch_remap_io_page_range(), and their physical address cannot be > obtained with a simple virt_to_phys(). > > A working patch is attached below, but there might (should ?) be a > better way to do it. Some of the code may also belong to > asm-generic/system.h instead of the RTDM skin. > > Note that you may also need to EXPORT_SYMBOL(vmlist and vmlist_lock) in > mm/vmalloc.c if you want to build the RTDM skin as a module. > > Comments ? In case no one comes up with an easy, portable way to detect remapped memory as well: What about some flags the caller of rtdm_mmap_to_user has to pass, telling what kind of memory it is? Would simplify the RTDM part, and the user normally knows quite well where the memory came from. And I love to break APIs. :) I'm CC'ing the first users of this service to ask for some feedback from their POV. Hope gna does not -once again- mangles the CCs. Jan [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 250 bytes --] ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Xenomai-core] [PATCH, RFC] Make ioremap'ed memory available through rtdm_mmap_to_user() 2006-09-15 16:40 ` Jan Kiszka @ 2006-09-18 21:13 ` Stelian Pop 2006-09-19 15:34 ` Jan Kiszka 0 siblings, 1 reply; 9+ messages in thread From: Stelian Pop @ 2006-09-18 21:13 UTC (permalink / raw) To: Jan Kiszka; +Cc: xenomai Le vendredi 15 septembre 2006 à 18:40 +0200, Jan Kiszka a écrit : > In case no one comes up with an easy, portable way to detect remapped > memory as well: What about some flags the caller of rtdm_mmap_to_user > has to pass, telling what kind of memory it is? Would simplify the RTDM > part, and the user normally knows quite well where the memory came from. > And I love to break APIs. :) This would be perfect. We could even reuse the prot field for that (PROT_READ | PROT_WRITE | PROT_VMALLOC | PROT_IOREMAP). Not the cleanest solution, but it won't break the API this way. Or maybe we should lower the API level a little bit, and let the user specify the physical address of the mapping instead of the virtual one.... Stelian. -- Stelian Pop <stelian.pop@domain.hid> ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Xenomai-core] [PATCH, RFC] Make ioremap'ed memory available through rtdm_mmap_to_user() 2006-09-18 21:13 ` Stelian Pop @ 2006-09-19 15:34 ` Jan Kiszka 2006-09-22 8:35 ` Stelian Pop 0 siblings, 1 reply; 9+ messages in thread From: Jan Kiszka @ 2006-09-19 15:34 UTC (permalink / raw) To: Stelian Pop; +Cc: xenomai [-- Attachment #1.1: Type: text/plain, Size: 1237 bytes --] Stelian Pop wrote: > Le vendredi 15 septembre 2006 à 18:40 +0200, Jan Kiszka a écrit : > >> In case no one comes up with an easy, portable way to detect remapped >> memory as well: What about some flags the caller of rtdm_mmap_to_user >> has to pass, telling what kind of memory it is? Would simplify the RTDM >> part, and the user normally knows quite well where the memory came from. >> And I love to break APIs. :) > > This would be perfect. We could even reuse the prot field for that > (PROT_READ | PROT_WRITE | PROT_VMALLOC | PROT_IOREMAP). Not the cleanest > solution, but it won't break the API this way. It would not change the function signature, but its argument semantics. We should better make a clean cut which signals via compiler errors that something changed. > > Or maybe we should lower the API level a little bit, and let the user > specify the physical address of the mapping instead of the virtual > one.... How would this help? You still need the virtual address for VMA blocks in order to collect the pages. I really think a separate mem-type argument is what we should do. And here comes a first patch in this direction. Only compile-tested so far, feedback is welcome. Jan [-- Attachment #1.2: rtdm-mmap-ioremap.patch --] [-- Type: text/plain, Size: 3420 bytes --] Index: include/rtdm/rtdm_driver.h =================================================================== --- include/rtdm/rtdm_driver.h (revision 1648) +++ include/rtdm/rtdm_driver.h (working copy) @@ -1021,6 +1021,25 @@ int rtdm_mutex_timedlock(rtdm_mutex_t *m /* --- utility functions --- */ +/*! + * @addtogroup util + * @{ + */ + +/*! + * @anchor RTDM_MEMTYPE_xxx @name Memory Types + * Flags defining the type of a memory region + * @{ + */ +/** Allocated with kmalloc() */ +#define RTDM_MEMTYPE_KMALLOC 0x00 +/** Remapped physical memory */ +#define RTDM_MEMTYPE_IOREMAP 0x01 +/** Allocated with vmalloc() */ +#define RTDM_MEMTYPE_VMALLOC 0x02 +/** @} Memory Types */ +/** @} util */ + #define rtdm_printk(format, ...) printk(format, ##__VA_ARGS__) #ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */ @@ -1036,7 +1055,7 @@ static inline void rtdm_free(void *ptr) #ifdef CONFIG_XENO_OPT_PERVASIVE int rtdm_mmap_to_user(rtdm_user_info_t *user_info, void *src_addr, size_t len, - int prot, void **pptr, + int mem_type, int prot, void **pptr, struct vm_operations_struct *vm_ops, void *vm_private_data); int rtdm_munmap(rtdm_user_info_t *user_info, void *ptr, size_t len); Index: ksrc/skins/rtdm/drvlib.c =================================================================== --- ksrc/skins/rtdm/drvlib.c (revision 1648) +++ ksrc/skins/rtdm/drvlib.c (working copy) @@ -1369,6 +1369,7 @@ void rtdm_nrtsig_pend(rtdm_nrtsig_t *nrt #if defined(CONFIG_XENO_OPT_PERVASIVE) || defined(DOXYGEN_CPP) struct rtdm_mmap_data { void *src_addr; + int mem_type; struct vm_operations_struct *vm_ops; void *vm_private_data; }; @@ -1386,7 +1387,7 @@ static int rtdm_mmap_buffer(struct file size = vma->vm_end - vma->vm_start; #ifdef CONFIG_MMU - if ((vaddr >= VMALLOC_START) && (vaddr < VMALLOC_END)) { + if (mmap_data->mem_type == RTDM_MEMTYPE_VMALLOC) { unsigned long mapped_size = 0; XENO_ASSERT(RTDM, (vaddr == PAGE_ALIGN(vaddr)), return -EINVAL); @@ -1419,6 +1420,8 @@ static struct file_operations rtdm_mmap_ * device operation handler * @param[in] src_addr Kernel address to be mapped * @param[in] len Length of the memory range + * @param[in] mem_type Type of the passed memory range, see + * @ref RTDM_MEMTYPE_xxx * @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 @@ -1463,11 +1466,12 @@ static struct file_operations rtdm_mmap_ * Rescheduling: possible. */ int rtdm_mmap_to_user(rtdm_user_info_t *user_info, void *src_addr, size_t len, - int prot, void **pptr, + int mem_type, int prot, void **pptr, struct vm_operations_struct *vm_ops, void *vm_private_data) { - struct rtdm_mmap_data mmap_data = {src_addr, vm_ops, vm_private_data}; + struct rtdm_mmap_data mmap_data = { src_addr, mem_type, vm_ops, + vm_private_data }; struct file *filp; const struct file_operations *old_fops; void *old_priv_data; [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 250 bytes --] ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Xenomai-core] [PATCH, RFC] Make ioremap'ed memory available through rtdm_mmap_to_user() 2006-09-19 15:34 ` Jan Kiszka @ 2006-09-22 8:35 ` Stelian Pop 2006-09-22 8:58 ` Jan Kiszka 0 siblings, 1 reply; 9+ messages in thread From: Stelian Pop @ 2006-09-22 8:35 UTC (permalink / raw) To: Jan Kiszka; +Cc: xenomai [Sorry for the delay, I was quite busy those days and unable to test the patch...] Le mardi 19 septembre 2006 à 17:34 +0200, Jan Kiszka a écrit : > > > > Or maybe we should lower the API level a little bit, and let the user > > specify the physical address of the mapping instead of the virtual > > one.... > > How would this help? You still need the virtual address for VMA blocks > in order to collect the pages. Actualy we need both the virtual address (for vmalloc case) and the physical address (for ioremap case). > + if (mmap_data->mem_type == RTDM_MEMTYPE_VMALLOC) { [...] This still won't work because for RTDM_MEMTYPE_IOREMAP virt_to_phys((void *)vaddr) doesn't return the physical address. So we still need to either: a) walk the vmlist struct to find out the needed vm->phys_addr (which will probably won't work in 2.4, or even in earlier 2.6 kernels) b) pass both the physical and the virtual adresses in the rtdm_mmap_to_user prototype (the physical address would be used only when RTDM_MEMTYPE_IOREMAP is specified) c) make 'src_addr' be a virtual address in some cases, and a physical address in ioremap case. d) make a special rtdm_mmap_iomem_to_user() function... The (tested) patch below implements the b) case. Index: include/rtdm/rtdm_driver.h =================================================================== --- include/rtdm/rtdm_driver.h (révision 1652) +++ include/rtdm/rtdm_driver.h (copie de travail) @@ -1021,6 +1021,25 @@ /* --- utility functions --- */ +/*! + * @addtogroup util + * @{ + */ + +/*! + * @anchor RTDM_MEMTYPE_xxx @name Memory Types + * Flags defining the type of a memory region + * @{ + */ +/** Allocated with kmalloc() */ +#define RTDM_MEMTYPE_KMALLOC 0x00 +/** Remapped physical memory */ +#define RTDM_MEMTYPE_IOREMAP 0x01 +/** Allocated with vmalloc() */ +#define RTDM_MEMTYPE_VMALLOC 0x02 +/** @} Memory Types */ +/** @} util */ + #define rtdm_printk(format, ...) printk(format, ##__VA_ARGS__) #ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */ @@ -1035,8 +1054,9 @@ } #ifdef CONFIG_XENO_OPT_PERVASIVE -int rtdm_mmap_to_user(rtdm_user_info_t *user_info, void *src_addr, size_t len, - int prot, void **pptr, +int rtdm_mmap_to_user(rtdm_user_info_t *user_info, + void *src_vaddr, unsigned long src_paddr, size_t len, + int mem_type, int prot, void **pptr, struct vm_operations_struct *vm_ops, void *vm_private_data); int rtdm_munmap(rtdm_user_info_t *user_info, void *ptr, size_t len); Index: ksrc/skins/rtdm/drvlib.c =================================================================== --- ksrc/skins/rtdm/drvlib.c (révision 1652) +++ ksrc/skins/rtdm/drvlib.c (copie de travail) @@ -1368,7 +1368,9 @@ #if defined(CONFIG_XENO_OPT_PERVASIVE) || defined(DOXYGEN_CPP) struct rtdm_mmap_data { - void *src_addr; + void *src_vaddr; + unsigned long src_paddr; + int mem_type; struct vm_operations_struct *vm_ops; void *vm_private_data; }; @@ -1376,17 +1378,22 @@ static int rtdm_mmap_buffer(struct file *filp, struct vm_area_struct *vma) { struct rtdm_mmap_data *mmap_data = filp->private_data; - unsigned long vaddr, maddr, size; + unsigned long vaddr, paddr, maddr, size; vma->vm_ops = mmap_data->vm_ops; vma->vm_private_data = mmap_data->vm_private_data; - vaddr = (unsigned long)mmap_data->src_addr; + vaddr = (unsigned long)mmap_data->src_vaddr; maddr = vma->vm_start; size = vma->vm_end - vma->vm_start; + if (mmap_data->mem_type == RTDM_MEMTYPE_IOREMAP) + paddr = mmap_data->src_paddr; + else + paddr = virt_to_phys((void *)vaddr); + #ifdef CONFIG_MMU - if ((vaddr >= VMALLOC_START) && (vaddr < VMALLOC_END)) { + if (mmap_data->mem_type == RTDM_MEMTYPE_VMALLOC) { unsigned long mapped_size = 0; XENO_ASSERT(RTDM, (vaddr == PAGE_ALIGN(vaddr)), return -EINVAL); @@ -1403,8 +1410,7 @@ return 0; } else #endif /* CONFIG_MMU */ - return xnarch_remap_io_page_range(vma, maddr, - virt_to_phys((void *)vaddr), + return xnarch_remap_io_page_range(vma, maddr, paddr, size, PAGE_SHARED); } @@ -1417,8 +1423,12 @@ * * @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] src_vaddr Kernel virtual address to be mapped + * @param[in] src_paddr Kernel physical address to be mapped (used only for IO + * memory, i.e. mem_type=RTDM_MEMTYPE_IOREMAP) * @param[in] len Length of the memory range + * @param[in] mem_type Type of the passed memory range, see + * @ref RTDM_MEMTYPE_xxx * @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 @@ -1462,12 +1472,14 @@ * * Rescheduling: possible. */ -int rtdm_mmap_to_user(rtdm_user_info_t *user_info, void *src_addr, size_t len, - int prot, void **pptr, +int rtdm_mmap_to_user(rtdm_user_info_t *user_info, + void *src_vaddr, unsigned long src_paddr, size_t len, + int mem_type, int prot, void **pptr, struct vm_operations_struct *vm_ops, void *vm_private_data) { - struct rtdm_mmap_data mmap_data = {src_addr, vm_ops, vm_private_data}; + struct rtdm_mmap_data mmap_data = { src_vaddr, src_paddr, mem_type, + vm_ops, vm_private_data }; struct file *filp; const struct file_operations *old_fops; void *old_priv_data; -- Stelian Pop <stelian.pop@domain.hid> ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Xenomai-core] [PATCH, RFC] Make ioremap'ed memory available through rtdm_mmap_to_user() 2006-09-22 8:35 ` Stelian Pop @ 2006-09-22 8:58 ` Jan Kiszka 2006-09-22 11:34 ` Stelian Pop 0 siblings, 1 reply; 9+ messages in thread From: Jan Kiszka @ 2006-09-22 8:58 UTC (permalink / raw) To: Stelian Pop; +Cc: xenomai [-- Attachment #1: Type: text/plain, Size: 1591 bytes --] Stelian Pop wrote: > [Sorry for the delay, I was quite busy those days and unable to test the > patch...] > > Le mardi 19 septembre 2006 à 17:34 +0200, Jan Kiszka a écrit : >>> Or maybe we should lower the API level a little bit, and let the user >>> specify the physical address of the mapping instead of the virtual >>> one.... >> How would this help? You still need the virtual address for VMA blocks >> in order to collect the pages. > > Actualy we need both the virtual address (for vmalloc case) and the > physical address (for ioremap case). > >> + if (mmap_data->mem_type == RTDM_MEMTYPE_VMALLOC) { > [...] > > This still won't work because for RTDM_MEMTYPE_IOREMAP > virt_to_phys((void *)vaddr) doesn't return the physical address. > > So we still need to either: > a) walk the vmlist struct to find out the needed vm->phys_addr (which > will probably won't work in 2.4, or even in earlier 2.6 kernels) Sounds fragile, indeed. > > b) pass both the physical and the virtual adresses in the > rtdm_mmap_to_user prototype (the physical address would be used only > when RTDM_MEMTYPE_IOREMAP is specified) Hmm, a bit ugly, this long argument list. > > c) make 'src_addr' be a virtual address in some cases, and a physical > address in ioremap case. That's so far the cleanest solution in my eyes. > > d) make a special rtdm_mmap_iomem_to_user() function... Also an option. Specifically, it wouldn't break the existing API... What about rtdm_iomap_to_user? Would you like to work out a patch in this direction? Jan [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 250 bytes --] ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Xenomai-core] [PATCH, RFC] Make ioremap'ed memory available through rtdm_mmap_to_user() 2006-09-22 8:58 ` Jan Kiszka @ 2006-09-22 11:34 ` Stelian Pop 2006-09-22 14:41 ` Jan Kiszka 0 siblings, 1 reply; 9+ messages in thread From: Stelian Pop @ 2006-09-22 11:34 UTC (permalink / raw) To: Jan Kiszka; +Cc: xenomai Le vendredi 22 septembre 2006 à 10:58 +0200, Jan Kiszka a écrit : > > d) make a special rtdm_mmap_iomem_to_user() function... > > Also an option. Specifically, it wouldn't break the existing API... What > about rtdm_iomap_to_user? Would you like to work out a patch in this > direction? Here it comes. Index: include/rtdm/rtdm_driver.h =================================================================== --- include/rtdm/rtdm_driver.h (révision 1652) +++ include/rtdm/rtdm_driver.h (copie de travail) @@ -1035,10 +1035,16 @@ } #ifdef CONFIG_XENO_OPT_PERVASIVE -int rtdm_mmap_to_user(rtdm_user_info_t *user_info, void *src_addr, size_t len, +int rtdm_mmap_to_user(rtdm_user_info_t *user_info, + void *src_addr, size_t len, int prot, void **pptr, struct vm_operations_struct *vm_ops, void *vm_private_data); +int rtdm_iomap_to_user(rtdm_user_info_t *user_info, + unsigned long src_addr, size_t len, + int prot, void **pptr, + struct vm_operations_struct *vm_ops, + void *vm_private_data); 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, Index: ksrc/skins/rtdm/drvlib.c =================================================================== --- ksrc/skins/rtdm/drvlib.c (révision 1652) +++ ksrc/skins/rtdm/drvlib.c (copie de travail) @@ -1368,7 +1368,8 @@ #if defined(CONFIG_XENO_OPT_PERVASIVE) || defined(DOXYGEN_CPP) struct rtdm_mmap_data { - void *src_addr; + void *src_vaddr; + unsigned long src_paddr; struct vm_operations_struct *vm_ops; void *vm_private_data; }; @@ -1376,16 +1377,22 @@ static int rtdm_mmap_buffer(struct file *filp, struct vm_area_struct *vma) { struct rtdm_mmap_data *mmap_data = filp->private_data; - unsigned long vaddr, maddr, size; + unsigned long vaddr, paddr, maddr, size; vma->vm_ops = mmap_data->vm_ops; vma->vm_private_data = mmap_data->vm_private_data; - vaddr = (unsigned long)mmap_data->src_addr; + vaddr = (unsigned long)mmap_data->src_vaddr; + paddr = (unsigned long)mmap_data->src_paddr; + if (!paddr) + /* kmalloc memory */ + paddr = virt_to_phys((void *)vaddr); + maddr = vma->vm_start; size = vma->vm_end - vma->vm_start; #ifdef CONFIG_MMU + /* Catch only vmalloc memory */ if ((vaddr >= VMALLOC_START) && (vaddr < VMALLOC_END)) { unsigned long mapped_size = 0; @@ -1403,8 +1410,7 @@ return 0; } else #endif /* CONFIG_MMU */ - return xnarch_remap_io_page_range(vma, maddr, - virt_to_phys((void *)vaddr), + return xnarch_remap_io_page_range(vma, maddr, paddr, size, PAGE_SHARED); } @@ -1412,12 +1418,51 @@ .mmap = rtdm_mmap_buffer, }; +static int __rtdm_do_mmap(rtdm_user_info_t *user_info, + struct rtdm_mmap_data *mmap_data, + size_t len, int prot, void **pptr) +{ + struct file *filp; + const struct file_operations *old_fops; + void *old_priv_data; + void *user_ptr; + + XENO_ASSERT(RTDM, xnpod_root_p(), return -EPERM;); + + 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 = mmap_data; + + 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 = (typeof(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; +} + + /** * 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] src_addr Kernel virtual 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 @@ -1462,50 +1507,84 @@ * * Rescheduling: possible. */ -int rtdm_mmap_to_user(rtdm_user_info_t *user_info, void *src_addr, size_t len, +int rtdm_mmap_to_user(rtdm_user_info_t *user_info, + void *src_addr, size_t len, int prot, void **pptr, struct vm_operations_struct *vm_ops, void *vm_private_data) { - struct rtdm_mmap_data mmap_data = {src_addr, vm_ops, vm_private_data}; - struct file *filp; - const struct file_operations *old_fops; - void *old_priv_data; - void *user_ptr; + struct rtdm_mmap_data mmap_data = { src_addr, 0, + vm_ops, vm_private_data }; + return __rtdm_do_mmap(user_info, &mmap_data, len, prot, pptr); +} - XENO_ASSERT(RTDM, xnpod_root_p(), return -EPERM;); +EXPORT_SYMBOL(rtdm_mmap_to_user); - filp = filp_open("/dev/zero", O_RDWR, 0); - if (IS_ERR(filp)) - return PTR_ERR(filp); +/** + * Map an I/O 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 I/O physical 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 + * @param[in] vm_ops vm_operations to be executed on the vma_area of the + * user memory range or NULL + * @param[in] vm_private_data Private data to be stored in the vma_area, + * primarily useful for vm_operation handlers + * + * @return 0 on success, otherwise (most common values): + * + * - -EINVAL is returned if an invalid start address, size, or destination + * address was passed. + * + * - -ENOMEM is returned if there is insufficient free memory or the limit of + * memory mapping for the user process was reached. + * + * - -EAGAIN is returned if too much memory has been already locked by the + * user process. + * + * - -EPERM @e may be returned if an illegal invocation environment is + * detected. + * + * @note RTDM supports two models for unmapping the user memory range again. + * One is explicite unmapping via rtdm_munmap(), either performed when the + * user requests it via an IOCTL etc. or when the related device is closed. + * The other is automatic unmapping, triggered by the user invoking standard + * munmap() or by the termination of the related process. To track release of + * the mapping and therefore relinquishment of the referenced physical memory, + * the caller of rtdm_mmap_to_user() can pass a vm_operations_struct on + * invocation, defining a close handler for the vm_area. See Linux + * documentaion (e.g. Linux Device Drivers book) on virtual memory management + * for details. + * + * Environments: + * + * This service can be called from: + * + * - Kernel module initialization/cleanup code + * - User-space task (non-RT) + * + * Rescheduling: possible. + */ +int rtdm_iomap_to_user(rtdm_user_info_t *user_info, + unsigned long src_addr, size_t len, + int prot, void **pptr, + struct vm_operations_struct *vm_ops, + void *vm_private_data) +{ + struct rtdm_mmap_data mmap_data = { NULL, src_addr, + vm_ops, vm_private_data }; - old_fops = filp->f_op; - filp->f_op = &rtdm_mmap_fops; - - old_priv_data = filp->private_data; - filp->private_data = &mmap_data; - - 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 = (typeof(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; + return __rtdm_do_mmap(user_info, &mmap_data, len, prot, pptr); } -EXPORT_SYMBOL(rtdm_mmap_to_user); +EXPORT_SYMBOL(rtdm_iomap_to_user); - /** * Unmap a user memory range. * -- Stelian Pop <stelian.pop@domain.hid> ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Xenomai-core] [PATCH, RFC] Make ioremap'ed memory available through rtdm_mmap_to_user() 2006-09-22 11:34 ` Stelian Pop @ 2006-09-22 14:41 ` Jan Kiszka 2006-09-22 14:53 ` Stelian Pop 0 siblings, 1 reply; 9+ messages in thread From: Jan Kiszka @ 2006-09-22 14:41 UTC (permalink / raw) To: Stelian Pop; +Cc: xenomai [-- Attachment #1: Type: text/plain, Size: 467 bytes --] Stelian Pop wrote: > Le vendredi 22 septembre 2006 à 10:58 +0200, Jan Kiszka a écrit : > >>> d) make a special rtdm_mmap_iomem_to_user() function... >> Also an option. Specifically, it wouldn't break the existing API... What >> about rtdm_iomap_to_user? Would you like to work out a patch in this >> direction? > > Here it comes. Your patch looks very good. Assuming that you have tested it successfully, I'm going to merge it soon. Thanks, Jan [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 250 bytes --] ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Xenomai-core] [PATCH, RFC] Make ioremap'ed memory available through rtdm_mmap_to_user() 2006-09-22 14:41 ` Jan Kiszka @ 2006-09-22 14:53 ` Stelian Pop 0 siblings, 0 replies; 9+ messages in thread From: Stelian Pop @ 2006-09-22 14:53 UTC (permalink / raw) To: Jan Kiszka; +Cc: xenomai Le vendredi 22 septembre 2006 à 16:41 +0200, Jan Kiszka a écrit : > Stelian Pop wrote: > > Le vendredi 22 septembre 2006 à 10:58 +0200, Jan Kiszka a écrit : > > > >>> d) make a special rtdm_mmap_iomem_to_user() function... > >> Also an option. Specifically, it wouldn't break the existing API... What > >> about rtdm_iomap_to_user? Would you like to work out a patch in this > >> direction? > > > > Here it comes. > > Your patch looks very good. Assuming that you have tested it > successfully, I did. > I'm going to merge it soon. Thanks. -- Stelian Pop <stelian.pop@domain.hid> ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2006-09-22 14:53 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2006-09-15 16:26 [Xenomai-core] [PATCH, RFC] Make ioremap'ed memory available through rtdm_mmap_to_user() Stelian Pop 2006-09-15 16:40 ` Jan Kiszka 2006-09-18 21:13 ` Stelian Pop 2006-09-19 15:34 ` Jan Kiszka 2006-09-22 8:35 ` Stelian Pop 2006-09-22 8:58 ` Jan Kiszka 2006-09-22 11:34 ` Stelian Pop 2006-09-22 14:41 ` Jan Kiszka 2006-09-22 14:53 ` Stelian Pop
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.