* [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.