[PATCH] Suggested FreeBSD merge
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
: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.
<dillon at xxxxxxxxxxxxx>
More information about the Submit