From: Jan Kiszka <kiszka@domain.hid>
To: Rodrigo Rosenfeld Rosas <lbocseg@domain.hid>
Cc: xenomai@xenomai.org
Subject: Re: [Xenomai-help] RTDM mmap alternative
Date: Tue, 07 Feb 2006 18:38:24 +0100 [thread overview]
Message-ID: <43E8DB10.5000901@domain.hid> (raw)
In-Reply-To: <200602061900.35411.lbocseg@domain.hid>
[-- Attachment #1.1: Type: text/plain, Size: 2242 bytes --]
[snmp on web.de down, switching account]
Rodrigo Rosenfeld Rosas wrote:
> Hi Jan,
>
>> ...
>> What precisely? I suggested to look at remap_pfn_range() or
>> io_remap_page_range(). Do you see problems when using one of them?
>
> This is the function prototype:
>
> int remap_pfn_range(struct vm_area_struct *vma,
> unsigned long virt_addr, unsigned long pfn,
> unsigned long size, pgprot_t prot);
>
> When a mmap call is issued, the vma structure is already initially filled. I
> don't know how to fill it and LDD3 doesn't explain it:
>
> "The arguments to remap_pfn_range are fairly straightforward, and most of them
> are already provided to you in the VMA when your mmap method is called."
>
> "Note that the kernel maintains lists and trees of VMAs to optimize area
> lookup, and several fields of vm_area_struct are used to maintain this
> organization. Therefore, VMAs can?t be created at will by a driver, or the
> structures break."
>
> So, I don't know how to implement a mmap like ioctl. Any sugestions?
>
Well, I have to say sorry. I was obviously too optimistic about an easy
way to implement mmap-features outside a mmap handler. It's far more
complex.
Ok, we need some helper function in RTDM to make life easier for
driver developers. Attached is a draft to implement
void *rtdm_mmap_to_user(void *buffer, size_t length);
It can only be invoked on continuous kernel memory (kmalloc'ed or
ioremap'ped), but this should be sufficient for the intended
applications. And it only runs in Linux context of course.
I tested it (after figuring out what to do at all, and how to get it
working then...) with a simple demo that returns a shared kernel memory
block, mapped into user-space via an RTDM-IOCTL. I think you should
easily (now really!) adapt it to your needs. Please check if this
functions meets your requirements and works for more than one scenario.
If so, I will add it to official RTDM.
@all: I would be curious to hear any comment on my /dev/zero-trick to
invoke mmap in kernel-space. Is this an ugly hack or may it be worth
considering to apply on /dev/rtheap as well - to overcome the need for
this device (and related user errors...)?
Jan
[-- Attachment #1.2: rtmmap_drv.c --]
[-- Type: text/plain, Size: 4219 bytes --]
#include <linux/mman.h>
#define XENO_HEAP_MODULE
#include <asm-generic/system.h>
#include <rtdm/rtdm_driver.h>
#define BUFFER_SIZE 100000
struct demodrv_context {
void *buf;
};
int demo_open_rt(struct rtdm_dev_context *context,
rtdm_user_info_t *user_info,
int oflags)
{
struct demodrv_context *my_context;
unsigned long vaddr;
my_context = (struct demodrv_context *)context->dev_private;
my_context->buf = kmalloc(BUFFER_SIZE, 0);
/* mark pages reserved so that remap_pfn_range works */
for (vaddr = (unsigned long)my_context->buf;
vaddr < (unsigned long)my_context->buf + BUFFER_SIZE;
vaddr += PAGE_SIZE)
SetPageReserved(virt_to_page(vaddr));
*(int *)my_context->buf = 1234;
return 0;
}
int demo_close_rt(struct rtdm_dev_context *context,
rtdm_user_info_t *user_info)
{
struct demodrv_context *my_context;
my_context = (struct demodrv_context *)context->dev_private;
printk("%d\n", *((int *)my_context->buf + 1000));
kfree(my_context->buf);
return 0;
}
/* *** RTDM mmap helper *** */
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);
return 0;
}
static struct file_operations rtdm_mmap_fops = {
.mmap = rtdm_mmap_buffer,
};
void *rtdm_mmap_to_user(void *buffer, size_t length)
{
struct file *filp;
struct file_operations *old_fops;
void *old_priv_data;
void *user_addr;
filp = filp_open("/dev/zero", O_RDWR, 0);
if (IS_ERR(filp)) {
printk("open failed\n");
return filp;
}
old_fops = filp->f_op;
filp->f_op = &rtdm_mmap_fops;
old_priv_data = filp->private_data;
filp->private_data = buffer;
down_write(¤t->mm->mmap_sem);
user_addr = (void *)do_mmap(filp, 0, length, PROT_READ|PROT_WRITE, MAP_SHARED, 0);
up_write(¤t->mm->mmap_sem);
filp->f_op = old_fops;
filp->private_data = old_priv_data;
filp_close(filp, current->files);
return user_addr;
}
/* *** End of RTDM mmap helper *** */
int demo_ioctl_rt(struct rtdm_dev_context *context,
rtdm_user_info_t *user_info,
int request,
void *arg)
{
struct demodrv_context *my_context;
my_context = (struct demodrv_context *)context->dev_private;
printk("buf = %p:%x\n", my_context->buf, *(int *)my_context->buf);
*(void **)arg = rtdm_mmap_to_user(my_context->buf, BUFFER_SIZE);
printk("rtdm_mmap = %p %d\n", *(void **)arg, *(int *)arg);
return 0;
}
static struct rtdm_device demo_device = {
struct_version: RTDM_DEVICE_STRUCT_VER,
device_flags: RTDM_NAMED_DEVICE,
context_size: sizeof(struct demodrv_context),
device_name: "demodev0",
open_rt: NULL,
open_nrt: demo_open_rt,
ops: {
close_rt: NULL,
close_nrt: demo_close_rt,
ioctl_rt: NULL,
ioctl_nrt: demo_ioctl_rt,
read_rt: NULL,
read_nrt: NULL,
write_rt: NULL,
write_nrt: NULL,
recvmsg_rt: NULL,
recvmsg_nrt: NULL,
sendmsg_rt: NULL,
sendmsg_nrt: NULL,
},
device_class: RTDM_CLASS_EXPERIMENTAL,
device_sub_class: 222,
driver_name: "demodrv",
peripheral_name: "demodev",
provider_name: "-",
proc_name: demo_device.device_name,
};
int init_module(void)
{
int ret;
ret = rtdm_dev_register(&demo_device);
printk("rtdm_dev_register = %d\n", ret);
return ret;
}
void cleanup_module(void)
{
rtdm_dev_unregister(&demo_device, 1000);
}
[-- Attachment #1.3: rtmmap.c --]
[-- Type: text/plain, Size: 385 bytes --]
#include <stdio.h>
#include <unistd.h>
#include <rtdm/rtdm.h>
int main()
{
int f = rt_dev_open("demodev0", 0);
void *p;
printf("open = %d\n", f);
printf("ioctl = %d\n", rt_dev_ioctl(f, 0, &p));
printf("*p = %d, p = %p\n", *((int *)p), p);
sleep(10);
*((int *)p + 1000) = 5678;
printf("close = %d\n", rt_dev_close(f));
return 0;
}
[-- Attachment #1.4: GNUmakefile --]
[-- Type: text/plain, Size: 217 bytes --]
all:
make -C /usr/src/linux-2.6.14-ipipe SUBDIRS=/usr/src/rtmmap modules
gcc -o rtmmap rtmmap.c `/usr/src/xenomai/bin/bin/xeno-config --xeno-cflags` `/usr/src/xenomai/bin/bin/xeno-config --xeno-ldflags` -lrtdm
[-- Attachment #1.5: Makefile --]
[-- Type: text/plain, Size: 91 bytes --]
EXTRA_CFLAGS += -I /usr/src/linux-2.6.14-ipipe/include/xenomai
obj-m += rtmmap_drv.o
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 250 bytes --]
next prev parent reply other threads:[~2006-02-07 17:38 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-02-03 19:27 [Xenomai-help] RTDM mmap alternative Rodrigo Rosenfeld Rosas
2006-02-04 9:07 ` Jan Kiszka
2006-02-04 12:44 ` Rodrigo Rosenfeld Rosas
2006-02-04 12:41 ` Jan Kiszka
2006-02-04 14:19 ` Rodrigo Rosenfeld Rosas
2006-02-06 21:00 ` Rodrigo Rosenfeld Rosas
2006-02-07 17:38 ` Jan Kiszka [this message]
2006-02-07 19:22 ` Rodrigo Rosenfeld Rosas
2006-02-07 20:03 ` Jan Kiszka
2006-02-08 2:15 ` Rodrigo Rosenfeld Rosas
2006-02-08 12:43 ` Rodrigo Rosenfeld Rosas
2006-02-08 13:14 ` Jan Kiszka
2006-02-08 18:03 ` Rodrigo Rosenfeld Rosas
2006-02-08 18:26 ` Jan Kiszka
2006-02-08 19:35 ` Rodrigo Rosenfeld Rosas
2006-02-08 19:07 ` Rodrigo Rosenfeld Rosas
2006-02-08 21:28 ` Rodrigo Rosenfeld Rosas
2006-02-09 8:53 ` Jan Kiszka
2006-02-09 16:04 ` Rodrigo Rosenfeld Rosas
2006-02-09 16:53 ` Jan Kiszka
2006-02-09 17:58 ` Rodrigo Rosenfeld Rosas
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=43E8DB10.5000901@domain.hid \
--to=kiszka@domain.hid \
--cc=lbocseg@domain.hid \
--cc=xenomai@xenomai.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.