[PATCH] Add compatibility <sys/io.h>

Bruce Evans brde at optusnet.com.au
Sat Mar 10 13:26:34 UTC 2012


Top posting.

Why should I have deleted this instead of replying?

On Fri, 9 Mar 2012, Adrian Chadd wrote:

> I really, really don't like the idea of having the same function have
> different argument orders based on the include file you're using.
>
> That will lead to all kinds of weird ass debugging issues later on.
>
> Why is it that we can't fix the upstream code?

> On 9 March 2012 13:36, Robert Millan <rmh at freebsd.org> wrote:
>> This patch adds a compatibility <sys/io.h> that would make it easier
>> to build on FreeBSD software that has been written for glibc (see
>> example1.c).

I somehow missed the original mail.

cpufunc.h has no user-serving parts inside, so it can't conflict with
any legal include.  However, abusing it in userland is convenient.

Even using the port i/o functions in it in the kernel is an error.
Bus space functions should be used instead.  However, the i/o functions
in it are much older than bus space, and abusing them in MD code in
the kernel is convenient.

>> The functionality in <sys/io.h> is more or less equivalent to
>> <machine/cpufunc.h> but provides some declarations which are
>> incompatible with those in <machine/cpufunc.h>. One of these cases is
>> very unfortunate because it alters I/O semantics, it applies to
>> outb(), outw() and outl():

All of it?  It has many other mistakes.  I doubt anything would duplicate
them all :-).

>>  FreeBSD code: outw(port, data);
>>  Glibc code: outw(data, port);

The FreeBSD order seemed natural to me since I was familiar with
Intel/DOS and they never used AT&T asm order.  I put the i/o functions
in cpufunc.h, but 386BSD seems to have had them in the Intel order,
since 4.4BSD has them in Intel order.

>> The undefined I/O behaviour that could potentially result from this is
>> very scary. Because of this I've written a few checks to prevent both
>> headers from being used at the same time. Overall, aside from the
>> portability benefit, my proposed addition has some less obvious
>> side-effects:

#error "no user serving parts inside" would prevent cpufunc.h being abused
at any time :-).

>>     Desireable side-effect: Adding <sys/io.h> would break
>> buildability of code that attempts to use both headers at the same
>> time _WITHOUT_ changing the outw() call semantics (see example2.c).

A sys header is more unsuitable, since this is very machine-dependent.
Even bus space's header is not in sys (it is <machine/bus.h>), though
many of its APIs are MI (with very MD internals for the typeded types).

Userland has even more reasons to avoid the machine dependencies.
Bus space is more complex, but seems to work OK in userland:

% #include <sys/types.h>
% #include <machine/bus.h>
% 
% void
% my_outb(unsigned int port, unsigned char data)
% {
% 	bus_space_write_1(X86_BUS_SPACE_IO, port, 0, data);
% }

This gives only minor pessimizations relative to the raw inline asm
outb().

To get this to work, I had to work around the following problems:
- the prerequisite <sys/types.h> is undocumented
- someone renamed I386_BUS_SPACE_IO and AMD64_BUS_SPACE_IO to
   X86_BUS_SPACE_IO.  This gives portability problems, and I only remembered
   the old names.  Having the machine name in the API at all is a bug.
   Especially for BUS_SPACE_MEM, the machine arch can't make any difference.
   There might be different types of memory mapped i/o, but a plain MEM should
   mean "ordinary" memory, or the least-extraordinary memory that the machine
   has, or if that is too extraordinary, then just don't implement
   BUS_TYPE_MEM.  Similarly for IO.  It means port i/o for x86, and jusr
   including the x86 header says that you want the x86 version of "ordinary"
   ports.
- <machine/bus.h> has undocumented namespace pollution.  It includes
   <machine/cpufunc.h>, and even uses outb() from it.  So I had to
   rename my function my_outb() to get it to compile.
- some of the undocumented namespace pollution can be killed by the
   BUS_SPACE_NO_LEGACY option.  This option is of course undocumented.
   It only kills the in/out i/o functions from <machine/cpufunc.h>,
   leaving all the other pollution, since it is intended for keeping
   bus space pure.  It is poorly implemented by defining the functions
   as syntactically correct expressions, after undefing inb and outb
   since it hasn't caught up with that becoming unnecessary a couple
   of years ago.  Anyway, this is no use for making the above compile
   with my_outb changed back to outb.  Since the polluting outb is
   still in the way.

Bruce


More information about the freebsd-arch mailing list