Alexander Leidinger

Just another weblog


Lin­ux­u­la­tor explained (for devel­op­ers): adding ioctls directly to the kernel

After giv­ing an overview of the in-kernel basics of the Lin­ux­u­la­tor, I want now to describe how to add sup­port for new ioctls to the Lin­ux­u­la­tor.

Where are the files to modify?

The plat­form inde­pen­dent code for the ioctls is in SRC/sys/compat/linux/linux_ioctl.c. The defines to have names for the ioctl val­ues are in SRC/sys/compat/linux/linux_ioctl.h.

How to mod­ify them?

First of all cre­ate a new header which will con­tain all the struc­tures, named val­ues and macros for those new ioctls. As writ­ten above, the ioctl val­ues (e.g. #define LINUX_VIDIOC_ENCODER_CMD 0x564d /* 0xc028564d */) do not belong there, they shall be added to linux_ioctl.h. Dur­ing the course of adding sup­port for ioctls, you will need this new header. Add it in the SRC/sys/compat/linux/ direc­tory, and pre­fix the name with a linux_. It would be good to decide on a com­mon tag here (ref­er­enced as yourtag in the fol­low­ing), and stay with it. Use it wher­ever you need to have some spe­cific name for the ioctl-set you want to add. In this case it would result in linux_yourtag.h (or even linux_ioctl_yourtag.h, depend­ing if this is used for some­thing very spe­cific to the ioctls, or some generic linux fea­ture) as the name of the header file. This was not done in the past, so do not expect that the names inside the linux_ioctl.c file will be con­sis­tent to this nam­ing scheme, but it is never too late to cor­rect mis­takes of the past (at least in Open Source soft­ware development).

Now add this header to linux_ioctl.c (you need to include compat/linux/linux_yourtag.h). After that add the ioctl val­ues to linux_ioctl.h. As can be seen above, the defines should be named the same as on linux, but with a LINUX_ pre­fix (make sure they where not defined before some­where else). The ioctl val­ues need to be the same hex val­ues as in Linux, off course. Sort them accord­ing to their hex value. When you added all, you need to add two more defines. The LINUX_IOCTL_yourtag_MIN and LINUX_IOCTL_yourtag_MAX ones. The MIN-one needs to be an alias for the first (sorted accord­ing to the hex value) ioctl you added, and MAX needs to be an alias for the last (again, sorted accord­ing to the hex value) ioctl you added.

The next step is to let the Lin­ux­u­la­tor know that it is able to han­dle the ioctls in the LINUX_IOCTL_yourtag_MIN to LINUX_IOCTL_yourtag_MAX range. Search the sta­tic linux_ioctl_function_t sec­tion of linux_ioctl.c and add such a vari­able for your ioctl set. The name of the vari­able should be some­thing like linux_ioctl_yourtag.

Sim­i­lar for the handler-definition for this. Search the sta­tic struct linux_ioctl_handler sec­tion and add a yourtag_handler. Set it to { linux_ioctl_yourtag, LINUX_IOCTL_yourtag_MIN, LINUX_IOCTL_yourtag_MAX }. To make this han­dler known to the Lin­ux­u­la­tor, you need to add it to the DATA_SET sec­tion. Add DATA_SET(linux_ioctl_handler_set, yourtag_handler) there.

Now the meat, the func­tion which han­dles the ioctls. You already defined it as linux_ioctl_function_t, but now you need to write it. The out­line of it looks like this:

static int
linux_ioctl_yourtag(struct thread *td, struct linux_ioctl_args *args)
        struct file *fp;
        int error;
        switch (args->cmd & 0xffff) {
        case LINUX_an_easy_ioctl:
        case LINUX_a_not_so_easy_ioctl:
                /* your handling of the ioctl */
                fdrop(fp, td);
                return (error);
        /* some more handling of your ioctls */
       return (ENOIOCTL);
        error = ioctl(td, (struct ioctl_args *)args);
        return (error);

An easy ioctl in the switch above is an ioctl where you do not have to do some­thing but can pass the ioctl through to FreeBSD itself. The not so easy ioctl case is an ioctl where you need to do e.g. a fget(td, args->fd, &fp). This is just an exam­ple, there are also other pos­si­bil­i­ties where you need to do addi­tional stuff before the return, or where you do not pass the ioctl to FreeBSD. A typ­i­cal exam­ple of what needs to be done here is to copy val­ues from linux struc­tures to FreeBSD struc­tures (and the other way too), or to trans­late between 64bit and 32bit. Linux pro­grams on amd64 are 32bit exe­cuta­bles and 32bit structures/pointers. To make this work on amd64, you need to find a way to map between the two. There are exam­ples in the ker­nel where this is already the case. The more promi­nent exam­ples in the 64bit<->32bit regard are the v4l and v4l2 ioctls.

The tedious part is to research if a trans­la­tion has to be done and if yes what needs to be trans­lated how. When this is done, most of the work is not so hard. The linux_yourtag.h should con­tain the struc­tures you need for this trans­la­tion work.

It is also pos­si­ble to add ioctls in a ker­nel mod­ule, but this is not sub­ject to this descrip­tion (I will update this post­ing with a link to it when I get time to write about it).


Tags: , , , , , , , , ,

v4l2 sup­port in the lin­ux­u­la­tor now in 8-stable

I MFCed the v4l2 sup­port in the lin­ux­u­la­tor to 8–sta­ble. This allows now to use v4l2–web­cams in skype/flash on 8-stable too.

Tags: , ,

Video4Linux2 sup­port in FreeBSD (linuxulator)

I com­mit­ted the v4l2 sup­port into the lin­ux­u­la­tor (in 9–cur­rent). Part of this was the import of the v4l2 header from linux. We have the per­mis­sion to use it (like the v4l one), it is not licensed via GPL. This means we can use it in FreeBSD native dri­vers, and they are even allowed to be com­piled into GENERIC (but I doubt we have a dri­ver which could pro­vide the v4l2 inter­face in GENERIC).

The code I com­mit­ted is “just” the glue-code which allows to use FreeBSD native devices which pro­vide a v4l2 inter­face (e.g. multimedia/pwcbsd or multimedia/webcamd) from linux programs.

Thanks to nox@ for writ­ing the glue code.

Tags: , , , , , , , , ,

DTrace probes for the Lin­ux­u­la­tor updated

If some­one had a look at the ear­lier post about DTrace probes for the Lin­ux­u­la­tor: I updated the patch at the same place. The dif­fer­ence between the pre­vi­ous one is that some D–scripts are fixed now to do what I meant, spe­cially the ones which pro­vide sta­tis­tics output.

Tags: , ,

New DTrace probes for the linuxulator

I for­ward ported my DTrace probes for the FreeBSD lin­ux­u­la­tor from a 2008-current to a recent –cur­rent. I have not the com­plete FreeBSD lin­ux­u­la­tor cov­ered, but a big part is already done. I can check the major locks in the lin­ux­u­la­tor, trace futexes, and I have a D-script which yells at a lot of errors which could hap­pen but should not.

Some of my D-scripts need some changes, as real-world test­ing showed that they are not really work­ing as expected. They can get over­whelmed by the amount of spec­u­la­tion and dynamic vari­ables (error mes­sage: dynamic vari­able drops with non-empty dirty list). For the dynamic vari­ables prob­lem I found a dis­cus­sion on the net with some sug­ges­tions. For the spec­u­la­tion part I expect sim­i­lar tuning-possibilities.

Unfor­tu­nately the D-script which checks the inter­nal locks fails to com­pile. Seems there is a lit­tle mis­un­der­stand­ing on my side how the D-language is sup­posed to work.

I try to get some time later to have a look at those problems.

Dur­ing my devel­op­ment I stum­bled over some generic DTrace prob­lems with the SDT provider I use for my probes:

  • If you load the Linux mod­ule after the SDT mod­ule, your sys­tem will panic as soon as you want to access some probes, e.g. “dtrace –l” will panic the sys­tem. Load­ing the Linux mod­ule before the SDT mod­ule pre­vents the panic.
  • Unload­ing the SDT mod­ule while the Linux mod­ule with the SDT probes is still loaded pan­ics the sys­tem too. Do not unload the Linux mod­ule if you run with my patch.

Accord­ing to avg@ those are known prob­lems, but I think nobody is work­ing on this. This is bad, because this means I can not com­mit my cur­rent patchset.

If some­one wants to try the new DTrace probes for the lin­ux­u­la­tor, feel free to go to and down­load linuxulator-dtrace.diff. I do not offer a work­ing hyper­link here on pur­pose, the SDT bugs can hurt if you are not care­ful, and I want to make the use of this patch a strong opt-in because of this. If the patch hurts you, it is your fault, you have been warned.

Tags: , , , , , , , , ,