[PATCH] Suggested FreeBSD merge

Matthew Dillon dillon at apollo.backplane.com
Sun Nov 14 11:52:23 PST 2004

:On Sun, Nov 14, 2004 at 10:23:55AM -0800, Matthew Dillon wrote:
:>     So, for example, I would never hard-code an actual fixed address.
:>     Instead I would take advantage of the fact that we are now in pure ELF
:>     environment and I would put some elf-loader glue in the kernel to
:>     resolve references to the kernel-supplied read-only mapping, or something
:>     like that, using a special ELF section.
:Hard-wiring the addresses is the only possibility for statically linked
:programs. E.g. a setup like this
:0xbfffff000 memmove
:0xbfffff100 htonl
:0xbfffff110 htons
:works, because it doesn't need .text relocations. This also works for
:shared libraries, because they can be statically linked against the
:addresses. The initialisation could be done either via a system call
:at init time ("load library page version 1.0") or directly by specifying
:an ABI version in the ELF header. Having something like that would be
:useful for emulation handling too. We could tag a binary as DragonFly 1.1
:program and the kernel could choose e.g. conversion of ioctl and other

    It won't work.  

    * Using 0xbffff000 presumes that the kernel was compiled to use only
      1GB of KVM.  This is the default for the kernel but by no means
      a requirement, and many people compile kernels with more or less KVM.

      BSD/OS used a similar hardwired addresses for PS_STRINGS in its
      binaries, and they were forced to change it to pass the address in
      %ebx on startup for precisely the same reason.

    * It makes emulation (of DragonFly) virtually impossible.

    * It greatly restricts backwards compatibility (ignoring the fact
      that the KVM size can change anyway).

    What we can do, even for a static binary, is create an ELF section
    with either a jump table or an array of function pointers which
    the kernel detects and initializes for the program, similar to the
    way e.g. Amiga shared library vector tables work.  The program can
    statically resolve to that table.

    We'd need a jump table anyway, since the procedures being provided may
    change size, so this would not create any additional cost.

    Also, using an ELF section like this gives the program the opportunity
    to supply its own 'default' procedure.  So, e.g. for the new system call
    subsystem the program itself would be able to decide how to deal with
    unrecognized system calls rather then the kernel seg-faulting the program
    out every time.


    What I recommend is that we have a .dragonfly.syscalls section and a
    .dragonfly.libcalls section.  We would implement htonl() and friends
    in the .dragonfly.libcalls section.

    The real question here is whether we should implement it has a jump
    table, embedding actual JMP instructions (an array of JMP instructions),
    or whether we should implement it simply as an array of pointers to

    Jeff and I played around with function pointers for the TCP dispatch
    code.  From playing around I came to the conclusion that the CPU's
    branch prediction cache seems to do such a good job with an indirect
    call that it is in fact just as fast as a direct call.  So I think
    my preference would be an array of function pointers.

					Matthew Dillon 
					<dillon at xxxxxxxxxxxxx>

More information about the Submit mailing list