Monthly Archives: August 2008

Unbreaking CVSup/amd64

When I recently upgraded my FreeBSD6/amd64 ``-STABLE'' machine, the CVSup binary on the system stopped working. CVSup would dump core consistently, shortly after connecting to the remote server. This rather unwelcome development took away my ability to keep my CVS trees upto-date; fixing the bug became top priority. The bug also turned out to be an interesting one.

The bug

Running CVSup after the upgrade to 6.3-PRERELEASE would result in a core dump shortly after connection establishment.

Program received signal SIGBUS, Bus error.
0x0000000800682d4f in fcntl () from /lib/libc.so.6
(gdb)
(gdb) disassemble fcntl
... snip ...
0x0000000800682d3f <fcntl+79>:  movaps %xmm4,0xffffffffffffffc1(%rax)
0x0000000800682d43 <fcntl+83>:  movaps %xmm3,0xffffffffffffffb1(%rax)
0x0000000800682d47 <fcntl+87>:  movaps %xmm2,0xffffffffffffffa1(%rax)
0x0000000800682d4b <fcntl+91>:  movaps %xmm1,0xffffffffffffff91(%rax)
0x0000000800682d4f <fcntl+95>:  movaps %xmm0,0xff
ffffffffffff81(%rax)
0x0000000800682d53 <fcntl+99>:  lea    0x110(%rsp),%rax
0x0000000800682d5b <fcntl+107>: movl   $0x10,0x20(%rsp)
0x0000000800682d63 <fcntl+115>: movl   $0x30,0x24(%rsp)
0x0000000800682d6b <fcntl+123>: mov    %rax,0x28(%rsp)
... snip ...

The faulting instruction was trying to save SSE registers to memory; and this was odd since there was no reason for this particular code path to be using SSE registers in the first place.

Rebuilding Modula-3 and CVSup from source did not fix the core dump, though the builds of these tools themselves completed without error. A search through the PR database revealed that other FreeBSD users had also been tripped by the bug: PR bin/124353.

A peek at the solution

Modula-3's runtime needed to be patched in the following way to fix this fault.

  • First, in $M3SRC/libs/m3core/src/unix/freebsd-4.amd64/Unix.i3, we declare the Modula-3 function Unix.fcntl() as being implemented externally by C function ufcntl().
    ... snip ...
    <*EXTERNAL "ufcntl"*> PROCEDURE fcntl (fd, request: int; arg: long): int;
    ... snip ...
    
  • Matching this declaration, an implementation of ufcntl() was provided in $M3SRC/libs/m3core/src/runtime/FBSD_AMD64/RTHeapDepC.c:
    ...
    #include <fcntl.h>
    ...
    int
    ufcntl(int fd, int cmd, long arg)
    {
           return (fcntl(fd, cmd, arg));
    }
        

On the surface, this "fix" does not seem to be doing anything. The ufcntl() entry point takes 3 arguments but it passes these down to fcntl() unchanged, and in the same order.

Yet, despite the apparent ``no op''-like nature of the change, the core dumps were gone.

Why this works

To understand why this fix works, we have to delve into the ABI; into the C calling conventions used for AMD64 code.

For normal function calls, the AMD64 calling convention passes upto 6 integer arguments in registers. Thus register %rdi would hold the first argument (fd in our case), register %rsi the second, cmd, register %rdx the third and so on. However, the C prototype for fcntl() is: int fcntl(fd, cmd, ...);, i.e., fcntl is a varargs function. Varargs functions use a different calling convention on the AMD64: register %rax is a ``hidden'' input parameter for these functions.

So, prior to the fix, the Modula-3 runtime was invoking fcntl() directly, but with registers set up for a non-varargs function call.

Now, as it turns out, in FreeBSD 6.2 and earlier, fcntl() in libc was not a C language function; rather it was implemented as an assembly language stub that invoked the SYS_fcntl system call. On the AMD64, FreeBSD's argument passing convention for system calls is close enough to the non-varargs C calling convention that the processor's registers happened to be correctly setup for a direct system call.

When fcntl() in libc was changed in FreeBSD 6-STABLE on 24 Apr 2008 to be a C function instead of a system call, things broke.

Though not obvious from just looking at the C code, the no-op like fix above works by using the C compiler to translate between the two calling conventions.

What's worrying

The relevant change to libc was in CVS/SVN HEAD for about 20 days before it was merged to -stable. CVSup is also a critical tool for the FreeBSD project. This bug was however only detected in -stable, and not in -current.

Unbreaking CVSup/amd64

When I recently upgraded my FreeBSD6/amd64 ``-STABLE'' machine, the CVSup binary on the system stopped working. CVSup would dump core consistently, shortly after connecting to the remote server. This rather unwelcome development took away my ability to keep my CVS trees upto-date; fixing the bug became top priority. The bug also turned out to be an interesting one.

The bug

Running CVSup after the upgrade to 6.3-PRERELEASE would result in a core dump shortly after connection establishment.

Program received signal SIGBUS, Bus error.
0x0000000800682d4f in fcntl () from /lib/libc.so.6
(gdb)
(gdb) disassemble fcntl
... snip ...
0x0000000800682d3f <fcntl+79>:  movaps %xmm4,0xffffffffffffffc1(%rax)
0x0000000800682d43 <fcntl+83>:  movaps %xmm3,0xffffffffffffffb1(%rax)
0x0000000800682d47 <fcntl+87>:  movaps %xmm2,0xffffffffffffffa1(%rax)
0x0000000800682d4b <fcntl+91>:  movaps %xmm1,0xffffffffffffff91(%rax)
0x0000000800682d4f <fcntl+95>:  movaps %xmm0,0xff
ffffffffffff81(%rax)
0x0000000800682d53 <fcntl+99>:  lea    0x110(%rsp),%rax
0x0000000800682d5b <fcntl+107>: movl   $0x10,0x20(%rsp)
0x0000000800682d63 <fcntl+115>: movl   $0x30,0x24(%rsp)
0x0000000800682d6b <fcntl+123>: mov    %rax,0x28(%rsp)
... snip ...

The faulting instruction was trying to save SSE registers to memory; and this was odd since there was no reason for this particular code path to be using SSE registers in the first place.

Rebuilding Modula-3 and CVSup from source did not fix the core dump, though the builds of these tools themselves completed without error. A search through the PR database revealed that other FreeBSD users had also been tripped by the bug: PR bin/124353.

A peek at the solution

Modula-3's runtime needed to be patched in the following way to fix this fault.

  • First, in $M3SRC/libs/m3core/src/unix/freebsd-4.amd64/Unix.i3, we declare the Modula-3 function Unix.fcntl() as being implemented externally by C function ufcntl().
    ... snip ...
    <*EXTERNAL "ufcntl"*> PROCEDURE fcntl (fd, request: int; arg: long): int;
    ... snip ...
    
  • Matching this declaration, an implementation of ufcntl() was provided in $M3SRC/libs/m3core/src/runtime/FBSD_AMD64/RTHeapDepC.c:
    ...
    #include <fcntl.h>
    ...
    int
    ufcntl(int fd, int cmd, long arg)
    {
           return (fcntl(fd, cmd, arg));
    }
        

On the surface, this "fix" does not seem to be doing anything. The ufcntl() entry point takes 3 arguments but it passes these down to fcntl() unchanged, and in the same order.

Yet, despite the apparent ``no op''-like nature of the change, the core dumps were gone.

Why this works

To understand why this fix works, we have to delve into the ABI; into the C calling conventions used for AMD64 code.

For normal function calls, the AMD64 calling convention passes upto 6 integer arguments in registers. Thus register %rdi would hold the first argument (fd in our case), register %rsi the second, cmd, register %rdx the third and so on. However, the C prototype for fcntl() is: int fcntl(fd, cmd, ...);, i.e., fcntl is a varargs function. Varargs functions use a different calling convention on the AMD64: register %rax is a ``hidden'' input parameter for these functions.

So, prior to the fix, the Modula-3 runtime was invoking fcntl() directly, but with registers set up for a non-varargs function call.

Now, as it turns out, in FreeBSD 6.2 and earlier, fcntl() in libc was not a C language function; rather it was implemented as an assembly language stub that invoked the SYS_fcntl system call. On the AMD64, FreeBSD's argument passing convention for system calls is close enough to the non-varargs C calling convention that the processor's registers happened to be correctly setup for a direct system call.

When fcntl() in libc was changed in FreeBSD 6-STABLE on 24 Apr 2008 to be a C function instead of a system call, things broke.

Though not obvious from just looking at the C code, the no-op like fix above works by using the C compiler to translate between the two calling conventions.

What's worrying

The relevant change to libc was in CVS/SVN HEAD for about 20 days before it was merged to -stable. CVSup is also a critical tool for the FreeBSD project. This bug was however only detected in -stable, and not in -current.

Summer tree cleaning

As you may know, I'm a user of the p4 side repository to do large code development. With the switch to svn, I wasn't sure I'd still need to do that, so I let my trees there go for a while. It is clear to me that I'll need to use p4 a little while longer. So, I cleaned up my newcard tree.Why do I need to cleanup at all? That's a good question. You'd think that you'd only have code cooking in the tree that was destined to be committed, so no cleanup is needed. Merging conflicts, sure, but no cleanup. Well, it turns out that sometimes perforce doesn't do quite the right thing when there's a loop back of new files into FreeBSD. If I create a file in perforce, and then later merge it into FreeBSD, then the $FreeBSD$ tag is messed up. Over time, you get lots of these files in the perforce tree, and you have to basically just copy the FreeBSD version over them.The other reason to clean up is that code can cook for too long. I have several projects in my newcard tree that just didn't work out. I didn't get them into the tree quickly enough and the problems they were designed to clean up have been solved in other ways. Or they fixed problems in the MD code, and now that FreeBSD has grown more machines more code needs to be changed. Sometimes you change the new MD code. Other times, you just junk the old stuff since the improvements were so marginal that it isn't worth carrying those stones in your kit bag anymore.Sometimes projects are only half-baked. I had a number of interesting ideas that turned out to not be such a good idea. That turned out to not be a big enough savings, or that some other key developer in the project didn't like. It happens. Some ideas are great, while others seem to be grating on others.So all of these are reasons to cleanup the tree. I've managed to reduce my diffs from 200k down to 100k. Most of the 100k that's left could easily be described as half-baked. The biggest half-baked thing is a port of the NetBSD improvements to mii. The second biggest are a collection of hacks and bug fixes to the pccard/cardbus layer. Those always take a lot of time to sort out.It is one of the more pedestrian things that I need to do when hacking. But if the litter piles up too high, it becomes increasingly difficult to see what should go into the tree, and what shouldn't so nothing does and many of my cool hacks don't benefit people, and I don't benefit from the wider exposure of the code. Nobody tests my private tree but me... Everybody notices when you put something even a little stinky into the main FreeBSD tree.I debated about not blogging about it. However, one reason people have told me they read my blog is that they learn how to be better engineers from some of the things I do. They usually don't tell me if they are emulating things I do because they think they are good, or if they are avoiding the things I do because they think they are bad. Maybe a little of both... Documenting the mundane from time to time may bring better balance. Or it may put my readers to sleep... It is hard to say without feedback...

Summer tree cleaning

As you may know, I'm a user of the p4 side repository to do large code development. With the switch to svn, I wasn't sure I'd still need to do that, so I let my trees there go for a while. It is clear to me that I'll need to use p4 a little while longer. So, I cleaned up my newcard tree.

Why do I need to cleanup at all? That's a good question. You'd think that you'd only have code cooking in the tree that was destined to be committed, so no cleanup is needed. Merging conflicts, sure, but no cleanup. Well, it turns out that sometimes perforce doesn't do quite the right thing when there's a loop back of new files into FreeBSD. If I create a file in perforce, and then later merge it into FreeBSD, then the $FreeBSD$ tag is messed up. Over time, you get lots of these files in the perforce tree, and you have to basically just copy the FreeBSD version over them.

The other reason to clean up is that code can cook for too long. I have several projects in my newcard tree that just didn't work out. I didn't get them into the tree quickly enough and the problems they were designed to clean up have been solved in other ways. Or they fixed problems in the MD code, and now that FreeBSD has grown more machines more code needs to be changed. Sometimes you change the new MD code. Other times, you just junk the old stuff since the improvements were so marginal that it isn't worth carrying those stones in your kit bag anymore.

Sometimes projects are only half-baked. I had a number of interesting ideas that turned out to not be such a good idea. That turned out to not be a big enough savings, or that some other key developer in the project didn't like. It happens. Some ideas are great, while others seem to be grating on others.

So all of these are reasons to cleanup the tree. I've managed to reduce my diffs from 200k down to 100k. Most of the 100k that's left could easily be described as half-baked. The biggest half-baked thing is a port of the NetBSD improvements to mii. The second biggest are a collection of hacks and bug fixes to the pccard/cardbus layer. Those always take a lot of time to sort out.

It is one of the more pedestrian things that I need to do when hacking. But if the litter piles up too high, it becomes increasingly difficult to see what should go into the tree, and what shouldn't so nothing does and many of my cool hacks don't benefit people, and I don't benefit from the wider exposure of the code. Nobody tests my private tree but me... Everybody notices when you put something even a little stinky into the main FreeBSD tree.

I debated about not blogging about it. However, one reason people have told me they read my blog is that they learn how to be better engineers from some of the things I do. They usually don't tell me if they are emulating things I do because they think they are good, or if they are avoiding the things I do because they think they are bad. Maybe a little of both... Documenting the mundane from time to time may bring better balance. Or it may put my readers to sleep... It is hard to say without feedback...

eee 901 wireless updates

I got a lovely little eee 901 for work. It mostly seems like a useful machine, except for the position of the right shift key which is a disaster. (Placing my fingers on the home row, I've hovering over the up-arrow instead of shift. Hilarity ensues when trying to type '~' in the terminal or working on spreadsheets in any way).


However, the wireless driver isn't integrated into the kernel yet, and the old driver tarball is already broken on 2.6.27 release candidates. I was having a hard time finding who was working on it or where the code was. So, I cobbled together the patches I found wandering around the internet, and put up a git repo:

git clone git://anongit.anholt.net/git/rt2860

Don't expect this repo to necessarily get updated, but it'll probably get you going if you're on 2.6.27-rc2 or so today.

eee 901 wireless updates

I got a lovely little eee 901 for work. It mostly seems like a useful machine, except for the position of the right shift key which is a disaster. (Placing my fingers on the home row, I've hovering over the up-arrow instead of shift. Hilarity ensues when trying to type '~' in the terminal or working on spreadsheets in any way).


However, the wireless driver isn't integrated into the kernel yet, and the old driver tarball is already broken on 2.6.27 release candidates. I was having a hard time finding who was working on it or where the code was. So, I cobbled together the patches I found wandering around the internet, and put up a git repo:

git clone git://anongit.anholt.net/git/rt2860

Don't expect this repo to necessarily get updated, but it'll probably get you going if you're on 2.6.27-rc2 or so today.

T-Mobile Dash experiment

I have two cell phones. One of this is my iPhone, made by Apple and running Apple's version of FreeBSD. The other is the T-Mobile Dash. I usually use my iPhone, but this weekend I was using the Dash to see how well it worked. It was no better or worse than the iPhone in the one area that I'd hoped it would be better at: call quality.

In the process of trying it out, I discovered the uipaq driver in FreeBSD. I wanted to use the Dash as a tethered phone. It is the whole reason I got it. Since the iPhone doesn't officially support tethering, I thought I'd give the Dash a try.

The uipaq driver was added to FreeBSD 7.0, ported from NetBSD which ported it from OpenBSD. Its roots go way back to the old Compaq iPaqs that were made years ago. This same basic interface has gone through only minor evolution in the interceding years. Unfortunately, I wasn't able to make it work with my phone due to some minor issues else where.

In the process of trying, I discovered there was no man page, so I snagged one from NetBSD and hacked it to account for the differences with FreeBSD. In searching how to setup the phone as a ppp link, I stumbled into a PR that greatly expanded the number of devices the driver recognizes and made it committable, I discovered that it wasn't built as a module, and I discovered that an old PDA I had in the garage would work with this driver, in addition to my HCT dash. All the easy problems I fixed...

So I moved the rock up the hill a little. I'll try another day to see if I can track down the issues that were else where in the kernel and see if I can punch entirely through to the other side. The lack of a tether solution has been the biggest disappointment with the iphone that I've had. While a number of interesting hackers are possible in that area, none of them are as easy and as simple as my old Sprint Samsung SPC-7600 was. The Dash also has bluetooth, which I'll give a spin after I can get it to connect with the wires...

None of this would be necessary if Apple didn't have such a tight control on what one can and cannot put on the phone. Well, control isn't the real issue. Rather, the issue is that they choose to control it in a way I don't like. If they controlled it in every way the same way I wanted to configure it, I doubt very many people would care... Since they don't, a lot of people are very interested in hacking it... but that's starting to get off topic...

Quick device_get_children cleanup

Hans Petter Selasky submitted a bug against the rather poor error handling of device_get_children a while ago. When the usb4bsd stuff he's trying to get into the tree was posted for review, one of the issues was with device_get_children() as it related to device_delete_children().

This reminded me of original issue. I've gone through the tree and done an audit of the device_get_children calls. I think that the issues have been resolved. However, it looks like there's a lot of code in the tree looking for siblings and such. This suggests a close review of the code to pull out common routines into subr_bus might be in order. Each of these hand-rolled routines had slightly different bugs in the error handling...

Mid august mips status update

Just wanted to jot out a quick status update on FreeBSD/mips.

A few weeks ago, diffs were sent out for review. The 6 patches are now down to three. gcc.diff, binutils.diff and pam.diff remain uncommitted.

pam.diff (now pam3.diff) has been receiving feedback from DES and others and is getting close. The first iteration was really far away from being commit quaility, but the last iteration may be the one that goes in.

gcc.diff has received feedback recently. Gonzo and I are in the process of digesting and understanding the feedback. We hope to produce a revised patch shortly, as there are a number of minor issues.

binutils.diff has had no comments. One person volunteered to look at it and commit it, but so far we're still waiting for feedback to make the patch better, or for it to be committed. If we don't hear anything one way or the other, I'll don my flame resistant suit and push it into the tree. There's really no issues with the patch that I can see. What is going to be a challenge is doing the vendor import of a few upstream files. Hopefully the volunteer will pull through and I won't have to learn how to do this in the new svn world. :-)

All the other diffs have been committed to the tree. It was gratifying to get positive feedback on them all, since I was worried more of them would have maintainer timeouts.

You can see the current set of patches in gonzo's patch directory. Grab only the latest pam patch there. The cddl.diff patch should be removed shortly, as I just committed it.

Had I been paying closer attention, I'd have written all this up for the FreeBSD status report.

continuing GEM progress

Just got back from a week in Hawaii with the family.  It was great to finally take a break, and come back refreshed instead of feeling overwhelmed.

Two weeks ago the good news for GEM was getting ReadPixels to go fast.  It should be fast under our architecture, since we can map the pages and get at them cached.  We just didn't get around to making sure that was the case for a while, and it turns out we had some traps.  Conformance tests that go and write a pixel, then read the value, then write a new pixel etc. were taking hours instead of the minutes that they should.  The fix was to make the fallback spans code (which is how our ReadPixels is handled, though this is pretty pessimal) use pread instead of mapping and reading the contents out.  This gave the kernel the information it needed to not clflush the whole buffer when you just needed a little bit out.  That fixed the conformance tests.  Once I combined that with a little cache of pread data so I didn't syscall per pixel, I was getting faster large-scale ReadPixels out of GEM than we'd seen out of the aperture reads that the driver's always used before.  And there's still significant room for improvement.

ReadPixels shouldn't be important.  In theory apps aren't doing this, since ReadPixels is so slow on just about everyone's hardware that you should figure out some way to get around using it.  But it turned out that at least gl-117 was actually using it, and it was a performance bottleneck, which is now almost gone (~10% of the profile).  So in this case conformance testing ended up forcing us to fix a real app bug.

I also fixed a couple of performance regressions seen on the 965 with openarena -- one was a failure in the drm-gem-merge branch, and another was cache ping-ponging for vertex/index buffer uploads since GTT mappings started happening.  It's now back up to 76 fps from 28 fps.

With our recent fixes plus the changes in response to lkml review, I'm ready to take another stab at getting into linux-next.  That's the gating step for releasing libdrm, then the 2d driver, then making an appropriate mesa tarball, then getting all the new hotness into distros.  It's been a long time coming.

continuing GEM progress

Just got back from a week in Hawaii with the family.  It was great to finally take a break, and come back refreshed instead of feeling overwhelmed.

Two weeks ago the good news for GEM was getting ReadPixels to go fast.  It should be fast under our architecture, since we can map the pages and get at them cached.  We just didn't get around to making sure that was the case for a while, and it turns out we had some traps.  Conformance tests that go and write a pixel, then read the value, then write a new pixel etc. were taking hours instead of the minutes that they should.  The fix was to make the fallback spans code (which is how our ReadPixels is handled, though this is pretty pessimal) use pread instead of mapping and reading the contents out.  This gave the kernel the information it needed to not clflush the whole buffer when you just needed a little bit out.  That fixed the conformance tests.  Once I combined that with a little cache of pread data so I didn't syscall per pixel, I was getting faster large-scale ReadPixels out of GEM than we'd seen out of the aperture reads that the driver's always used before.  And there's still significant room for improvement.

ReadPixels shouldn't be important.  In theory apps aren't doing this, since ReadPixels is so slow on just about everyone's hardware that you should figure out some way to get around using it.  But it turned out that at least gl-117 was actually using it, and it was a performance bottleneck, which is now almost gone (~10% of the profile).  So in this case conformance testing ended up forcing us to fix a real app bug.

I also fixed a couple of performance regressions seen on the 965 with openarena -- one was a failure in the drm-gem-merge branch, and another was cache ping-ponging for vertex/index buffer uploads since GTT mappings started happening.  It's now back up to 76 fps from 28 fps.

With our recent fixes plus the changes in response to lkml review, I'm ready to take another stab at getting into linux-next.  That's the gating step for releasing libdrm, then the 2d driver, then making an appropriate mesa tarball, then getting all the new hotness into distros.  It's been a long time coming.

Slimming down the NSLU kernel

A few days ago, I wrote about the NSLU kernel config file being committed to FreeBSD's svn tree. The default compressed kernel is about 1.6MB, but the size of the partition of the NSLU2's flash is 1.25MB, a gap of just under 300kB. With some hacking, I've been able to reduce the size of the kernel to fit.

The default kernel's text+data size is 3,425,844 bytes. Compressed, with the appropriate headers, this drops to 1,591,109 bytes. However, the goal is 1,310,720 bytes. We're short by at least 294,553 bytes of fitting into the kernel portion of the flash on the NSLU.

My first thought was to start cutting things out. I removed IPv6 (options INET6) since I didn't need it for my setup. This saved 210,797 bytes in the uncompressed kernel and 74,115 bytes in the compressed kernel. This one option shaved 5% (compressed) of the kernel size. A move in the right direction, but more was needed.

Next, I recalled from previous attempts that there's many inline functions that don't need to be inlined. There's a small performance gain from inlining these functions, but it can add a lot to the kernel. So I added three options to the kernel config:
options MUTEX_NOINLINE
options RWLOCK_NOINLINE
options SX_NOINLINE
This resulted in a size reduction of 432,984 bytes (uncompressed) and 87,289 bytes (compressed). This is also a significant savings, and meant that we'd saved 161,404 bytes in the compressed kernel so far. We were still ~133,000 bytes shy of the mark.

At this point I noticed that there were a lot of things in the kernel that weren't required for boot, and that had shown up as being larger. When doing the size reduction, often times I use the 'size' command to get the top 20 .o files to see if there's junk that can just be omitted from the kernel. In this case, I saw that usb, scsi and releated drivers consumed a lot of space. This could be loaded from a number of modules after boot if I was booting from a RAM disk. Since the plan was to put an initrd-like ram disk in the other partition of the flash, I went ahead and removed these pieces:
#device usb
#options USB_DEBUG
#device ohci
#device ehci
#device ugen
#device umass
#device scbus # SCSI bus (required for SCSI)
#device da # Direct Access (disks)
This trimming saved 278,837 bytes (uncompressed) and 133,520 bytes (compressed). This was huge, and brought the total trimmed up to 294,924 bytes. This is just barely over the line, so I thought I'd go for a little more.

Another big area of the kernel is the code brought in with 'options miibus' configuration line. This brings in all the phy drivers on the off chance you'll need it. In many embedded systems, you know which phy driver you have, and can wire in only the one or ones you need. Since I wasn't planning on using this box as a general purpose router, that needed to work with any Ethernet dongle that was plugged into the USB port, I went ahead and transitioned to this configuration. The NSLU has a RealTek Phy that needs the rlphy driver. This means that I changed the config file like so:
#device miibus # NB: required by npe
device mii
device rlphy
This option shaved a few more bytes off the total. 80,012 bytes (uncompressed) and 25,156 bytes (compressed).

At the end of all this, the compressed kernel had been reduced from 1,625,125 bytes down to 1,286,193 bytes, for a savings of 320,080 bytes. This was enough margin for me to feel comfortable trying to burn it into my NSLU. Unfortunately, I ran out of time tonight to try it, so the story of that experiment will wait for another post. Also, I don't know how to make blogspot do tables, or I'd have made some nice tables with all this data for this log.

There's likely more options that can be explored to squeeze even more bytes out of the kernel. bzip2 might be a good place to get maybe 10% more space back (at these sizes, an extra 100kB compressed, or 250kB uncompressed). The exploder for bzip2 is bigger and uses more memory.

Looking at the .o files that are laying around that pci.o is kinda big, suggesting that we need to break it up some more. In previous experiments, separating out the MSI and PCIe stuff helped quite a bit. I'm unsure what the best newbusly way to extract this functionality might be, but it could save us 20kB uncompressed (maybe 8k compressed, iirc).

There's a number of other places code is agresively inlined, these could be investigated. there's
a few things in the tree tagged as standard that likely could be made to be options. There's much room here to explore a number of different options to reduce the kernel size even further if the need presents itself.

The nfs server option is about 45kB. Soft updates run about the same. nfsv4 also eats a lot of memory (looks to be 55kB).

However, for all these options, it would be nice is the NAS could have RAID, FAT, ntfs, smbfs and ext2fs support as well. Continuing to trim would allow this more easily. Or at least eliminate the need for loadable modules.

This is to say, there's a lot of areas for further research and documentation. I didn't even look at using a /boot/loader either. Maybe that can be helpful... Maybe I'll turn that into a research paper for one of the conferences... Either the continued size reduction thing, or using /boot/loader.

Finally, I've uploaded the changed NSLU config file in case my verbal descriptions here were insufficient.

Getting online using FreeBSD and BSNL DataOne

BSNL's DataOne service (DSL) is straightforward to use in FreeBSD. The following recipe shows how to get online using PPPoE.

  • First, you need to configure your DSL modem as specified by the ISP. This procedure is modem-specific and your BSNL representative should be able to assist you here.
  • You would need the name of the ethernet interface to which your modem is attached. If you are unsure of what this is, use ifconfig(8) to find out.
  • Next, you need to add the following template text to /etc/ppp/ppp.conf:
    dataone:
     set device "PPPoE:*INTERFACE*"
     set authname "*YOUR-USERNAME*"
     set authkey "*YOUR-PASSWORD*"
     set dial
     enable dns
     add default HISADDR
    

    Replace *YOUR-USERNAME* and *YOUR-PASSWORD* with your DataOne user name and password respectively. Replace *INTERFACE* with the name of your network interface (i.e., "rl0" or "fxp0" or whatever).

  • Finally, invoke ppp(8) in the usual way:
    % ppp dataone
    ppp> dial
    ppp> ... the prompt changes as PPP negotiation proceeds ...
    PPP>
    

Thats, it! You should be online.

Getting online using FreeBSD and BSNL DataOne

BSNL's DataOne service (DSL) is straightforward to use in FreeBSD. The following recipe shows how to get online using PPPoE.

  • First, you need to configure your DSL modem as specified by the ISP. This procedure is modem-specific and your BSNL representative should be able to assist you here.
  • You would need the name of the ethernet interface to which your modem is attached. If you are unsure of what this is, use ifconfig(8) to find out.
  • Next, you need to add the following template text to /etc/ppp/ppp.conf:
    dataone:
     set device "PPPoE:*INTERFACE*"
     set authname "*YOUR-USERNAME*"
     set authkey "*YOUR-PASSWORD*"
     set dial
     enable dns
     add default HISADDR
    

    Replace *YOUR-USERNAME* and *YOUR-PASSWORD* with your DataOne user name and password respectively. Replace *INTERFACE* with the name of your network interface (i.e., "rl0" or "fxp0" or whatever).

  • Finally, invoke ppp(8) in the usual way:
    % ppp dataone
    ppp> dial
    ppp> ... the prompt changes as PPP negotiation proceeds ...
    PPP>
    

Thats, it! You should be online.

FreeBSD/avr32 spotted in the wild

A very preliminary port to the AVR32 has been spotted in the wild. Arnar Mar Sig posted a dmesg of FreeBSD/avr32. You can find his post through this link.

For those of you unfamiliar with the AVR32 architecture, it is an architecture that is used primarily in embedded applications. AVR may be initials familiar to many readers as microcontrollers. Atmel took its know-how and created a 32-bit version of this architecture basically from scratch.

You can find more information about the processor at atmel's web site, or at wikipedia.

The work here clearly is preliminary, but it is very cool none the less. FreeBSD embedded is on the move...

[[ typos corrected, I hope :-) ]]

Apple iPhone (3G) vs. FreeBSD, take I

No, this post won’t be able to tell you how to synchronize contacts, calendar, bookmarks etc. from your FreeBSD box to your iPhone or iPhone 3G, sorry – still working on that. It will, however, show you how to make FreeBSD recognize your iPhone as a camera device, so that you can download the photos taken with your iPhone to a FreeBSD host.

First of all, make sure you’re using a kernel with ugen(4) support – but either without uhid(4) support or FreeBSD 8-CURRENT in SVN revision 181482 or newer – or manually apply this patch:

[Update: I have just MFC'ed this patch to RELENG_7 (SVN revision 181636) and RELENG_6 (SVN revision 181637), so this patch will be included in FreeBSD 7.1 and 6.4].

Index: sys/dev/usb/usb_quirks.c
===================================================================
--- sys/dev/usb/usb_quirks.c	(revision 181481)
+++ sys/dev/usb/usb_quirks.c	(working copy)
@@ -106,6 +106,10 @@
 	ANY, { UQ_HID_IGNORE }},
  { USB_VENDOR_MGE, USB_PRODUCT_MGE_UPS2,
 	ANY, { UQ_HID_IGNORE }},
+ { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE,
+	ANY, { UQ_HID_IGNORE }},
+ { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE_3G,
+	ANY, { UQ_HID_IGNORE }},
 
  /* Devices which should be ignored by both ukbd and uhid */
  { USB_VENDOR_CYPRESS, USB_PRODUCT_CYPRESS_WISPY1A,
Index: sys/dev/usb/usbdevs
===================================================================
--- sys/dev/usb/usbdevs	(revision 181481)
+++ sys/dev/usb/usbdevs	(working copy)
@@ -853,6 +853,8 @@
 product APPLE IPOD_08		0x1208	iPod '08'
 product APPLE IPODVIDEO		0x1209	iPod Video
 product APPLE IPODNANO		0x120a	iPod Nano
+product APPLE IPHONE		0x1290	iPhone
+product APPLE IPHONE_3G		0x1292	iPhone 3G
 product APPLE ETHERNET		0x1402	Ethernet A1277
 
 /* Arkmicro Technologies */

Next, make sure you have graphics/gphoto2 and graphics/libgphoto2 (the latter needs to be 2.4.2_1 or later for the iPhone 3G to work) installed.

Plug in the USB cable from your iPhone and verify using dmesg(8) that it shows up as an ugen(4) device as shown below:

kernel: ugen1: <Apple Inc. iPhone, class 0/0, rev 2.00/0.01, addr 2> on uhub4

That’s it – you should now be able to access the photos on your iPhone using ghoto2(1) – just replace ‘Apple iPhone (PTP Mode)’ with ‘Apple iPhone 3G (PTP Mode)’ for the iPhone 3G:

$ gphoto2 --camera 'Apple iPhone (PTP Mode)' -L
There is no file in folder '/'.                                                
There is no file in folder '/store_00010002'.
There is no file in folder '/store_00010002/DCIM'.
There are 7 files in folder '/store_00010002/DCIM/100APPLE'.
#1     IMG_0007.JPG                   49 KB image/jpeg
#2     IMG_0013.JPG                  389 KB image/jpeg
#3     IMG_0022.JPG                   26 KB image/jpeg
#4     IMG_0026.JPG                  358 KB image/jpeg
#5     IMG_0027.JPG                  357 KB image/jpeg
#6     IMG_0028.JPG                  381 KB image/jpeg
#7     IMG_0029.JPG                  377 KB image/jpeg
There is no file in folder '/store_00010002/DCIM/999APPLE'.

See the gphoto2(1) man page for further usage instructions.

Of course, you can also use a graphical client such as graphics/gtkam as long as it uses libgphoto2 for camera access.

flattr this!

Firefox 3 cured

Recently I blew away ageing 6-STABLE on my workstation and installed afresh 7-STABLE. While at it, I decided to install Firefox3 instead of good ol’ Firefox2. It worked okay, but behold, on certain pages background images were replaced by random pieces of screen widgetry.

I was desperate.

Finally good folks of the FreeNode’s #freebsd-gnome channel, namely Zyl and miwi, told me the relevant more magic line for xorg.conf:

Option “XaaNoOffscreenPixmaps” “On”

And all is warm and cozy again. Thanks!

The FreeBSD IPv6 Wiki – now fully public

The main DNS record for the FreeBSD wiki (wiki.FreeBSD.org) has now been updated to include the IPv6 address record.
The server hosting the wiki, sky.FreeBSD.org, has been running with bz’s latest IPv6 jail patch for 10 days without issues.
See the freebsd-jail list for patches: http://lists.freebsd.org/pipermail/freebsd-jail/2008-July/000379.html

NSLU2 support committed to FreeBSD/arm

I just committed the basic Linksys NSLU2 support to the subversion tree. It boots and runs on an NFS root. We're currently lacking support for the leds, the buttons and the on-board flash. Here's some basic instructions if you want to try it on your NSLU2. They are adapted from Sam Leffler's README file for the AVILA, which is adapted from other sources, including Olivier Houchard's and my instructions that have appeared.

  1. Build world
  2. Setup NFS root
  3. Configure diskless system
  4. Build and Install Kernel
  5. Put Kernel in tftp area
  6. Boot from redboot


Build world

The FreeBSD handbook can help you find the sources, etc Once you have them, and they are from -CURRENT after 8am on 2008-08-03, you can proceed to build the world. Each section is cumulative from the previous section for simplicity sake.


setenv TARGET arm
setenv MAKEOBJDIRPREFIX /tmp/$USER/obj
setenv TARGET_BIG_ENDIAN t
setenv TARGET_CPU_TYPE xscale
make buildworld


Setup NFS root

Find a server that has some disk space. You'll need about 250MB of space for a full FreeBSD image.

setenv ROOT /data/freebsd/roots/slug
make installworld DESTDIR=$ROOT
mergemaster -m $SRC/etc -D $ROOT -i -A arm


Setup diskless system
diskless(8) gives a good overview in how to do this. It is left as an exercise for the read to come up with all the settings. Usually /etc/rc.conf and /etc/fstab must be configured. /etc/ttys is another one that usually needs some tlc. If there's enough demand, I'll write about this in the future.

Build and install the kernel

make KERNCONF=NSLU buildkernel
make KERNCONF=NSLU DESTDIR=$ROOT installkernel


Note: the NSLU kernel is configured with the root filesystem mounted via NFS over the npe0 wired interface.

You should now have an NFS-mountable root filesystem with a kernel. The final step is to setup network diskless booting from the board. It is assumed you have a DHCP server operating on your network and the server is configured to supply the necessary information in the DHCP lease. If you run the ISC DHCP server the following configuration information is an example of how to do this:

option root-opts code 130 = string; # NFS / mount options

host slug {
hardware ethernet 00:d0:12:02:47:68;
fixed-address 10.0.0.221;
next-server 10.0.0.251;
filename "kernel-slug.nfs";
option root-path "10.0.0.251:/data/freebsd/roots/slug";
option root-opts "nolockd";
}

Note: the root-opts item specifies the root filesystem should be mounted with the nolocked option; this just short-circuits file locking requests so you don't get complaints from programs that use the pidfile(3) routine (e.g. devd)

Install kernel in tftp area

Place the kernel in the TFTP area for booting from the prom monitor. If your TFTP server returns file from /tftpboot (default) then do something like:
cp $ROOT/boot/kernel/kernel /tftpboot/kernel-slug.nfs


Boot using Redboot

+(hit control C here)
RedBoot> ip -h 10.0.0.251 -l 10.0.0.1
IP: 10.0.0.1/255.255.255.0 Gateway: 0.0.0.0
Default server: 10.0.0.251
RedBoot> load -b 0x200000 kernel-avila.nfs
Using default protocol (TFTP)
Address offset = 0x40000000
Entry point: 0x00200100, address range: 0x00200000-0x004db2d4
RedBoot> go


dmesg
Here's a complete transcript of my doing this. The .gz file listed below really isn't the simple gz file, but rather kernel.gz.tramp from the kernel build. Also, I've hacked my NSLU to have a serial port, which make development like this easier. See the web for instructions on how to do a no-mod breakin.

+Ethernet eth0: MAC address 00:14:bf:68:47:ba
IP: 192.168.0.1/255.255.255.0, Gateway: 192.168.0.1
Default server: 0.0.0.0, DNS server IP: 0.0.0.0

RedBoot(tm) bootstrap and debug environment [ROMRAM]
Red Hat certified release, version 1.92 - built 15:16:07, Feb 3 2004

Platform: IXDP425 Development Platform (XScale)
Copyright (C) 2000, 2001, 2002, Red Hat, Inc.

RAM: 0x00000000-0x02000000, 0x000723a0-0x01ff3000 available
FLASH: 0x50000000 - 0x50800000, 64 blocks of 0x00020000 bytes each.
== Executing boot script in 2.000 seconds - enter ^C to abort
^C
RedBoot> ip -l 10.0.0.12 -h 10.0.0.8
IP: 10.0.0.12/255.255.255.0, Gateway: 192.168.0.1
Default server: 10.0.0.8, DNS server IP: 0.0.0.0
RedBoot> load -b 0x200000 kernel.nslu.gz
Using default protocol (TFTP)
Address offset = 0xf0000000
Entry point: 0x00200074, address range: 0x00200000-0x003830fc
RedBoot> go
KDB: debugger backends: ddb
KDB: current backend: ddb
Copyright (c) 1992-2008 The FreeBSD Project.
Copyright (c) 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994
The Regents of the University of California. All rights reserved.
FreeBSD is a registered trademark of The FreeBSD Foundation.
FreeBSD 8.0-CURRENT #12: Sun Aug 3 00:09:07 MDT 2008
imp@lighthouse:/tmp/imp/obj/arm/cache/svn/head/sys/NSLU
CPU: IXP425 266MHz rev 1 (ARMv5TE) (XScale core)
DC enabled IC enabled WB enabled LABT branch prediction enabled
32KB/32B 32-way Instruction cache
32KB/32B 32-way write-back-locking Data cache
real memory = 33554432 (32 MB)
avail memory = 25894912 (24 MB)
ixp0: on motherboard
pcib0: on ixp0
pci0: on pcib0
ohci0: irq 28 at device 1.0 on pci0
ohci0: [GIANT-LOCKED]
ohci0: [ITHREAD]
usb0: OHCI version 1.0
usb0: on ohci0
usb0: USB revision 1.0
usbd_get_string: getting lang failed, using 0
uhub0: on usb0
uhub0: 3 ports with 3 removable, self powered
ohci1: irq 27 at device 1.1 on pci0
ohci1: [GIANT-LOCKED]
ohci1: [ITHREAD]
usb1: OHCI version 1.0
usb1: on ohci1
usb1: USB revision 1.0
usbd_get_string: getting lang failed, using 0
uhub1: on usb1
uhub1: 2 ports with 2 removable, self powered
ehci0: irq 26 at device 1.2 on pci0
ehci0: [GIANT-LOCKED]
ehci0: [ITHREAD]
usb2: EHCI version 1.0
usb2: companion controllers, 3 ports each: usb0 usb1
usb2: on ehci0
usb2: USB revision 2.0
uhub2: on usb2
uhub2: 5 ports with 5 removable, self powered
ixpclk0: on ixp0
ixpiic0: on ixp0
iicbb0: on ixpiic0
iicbus0: on iicbb0 master-only
iicbus0: at addr 0
iic0: on iicbus0
ixpwdog0: on ixp0
uart0: on ixp0
uart0: [FILTER]
uart0: console (115200,n,8,1)
uart1: on ixp0
uart1: [FILTER]
ixpqmgr0: on ixp0
ixpqmgr0: [ITHREAD]
npe0: on ixp0
npe0: [ITHREAD]
npe0: remember to fix rx q setup
miibus0: on npe0
rlphy0: PHY 1 on miibus0
rlphy0: 10baseT, 10baseT-FDX, 100baseTX, 100baseTX-FDX, auto
npe0: Ethernet address: 00:14:bf:68:47:ba
npe1: on ixp0
npe1: [ITHREAD]
npe1: remember to fix rx q setup
npe1: Cannot find my PHY.
device_attach: npe1 attach returned 6
ixpclk0: [FILTER]
Timecounter "IXP425 Timer" frequency 66666600 Hz quality 1000
Timecounters tick every 10.000 msec
bootpc_init: wired to interface 'npe0'
Sending DHCP Discover packet from interface npe0 (00:14:bf:68:47:ba)
npe0: link state changed to UP
Received DHCP Offer packet on npe0 from 0.0.0.0 (accepted) (no root path)
Sending DHCP Request packet from interface npe0 (00:14:bf:68:47:ba)
Received DHCP Ack packet on npe0 from 0.0.0.0 (accepted) (got root path)
npe0 at 10.0.0.12 server 0.0.0.0 boot file kernel.slug
subnet mask 255.255.255.0 router 10.0.0.1 rootfs 10.0.0.8:/pe/slug rootopts nolockd
Adjusted interface npe0
Trying to mount root from nfs:
NFS ROOT: 10.0.0.8:/pe/slug
warning: no time-of-day clock registered, system time will not be set accurately
warning: no time-of-day clock registered, system time will not be set accurately
Interface npe0 IP-Address 10.0.0.12 Broadcast 10.0.0.255
Loading configuration files.
No suitable dump device was found.
Entropy harvesting: interrupts ethernet point_to_point kickstart.
Starting file system checks:
mount_nfs: can't update /var/db/mounttab for 10.0.0.8:/pe/slug
Setting hostuuid: 1c728616-1dd2-11b2-9fa6-0014bf6847ba.
Setting hostid: 0xb1c1273a.
Mounting local file systems:.
Setting hostname: slug.
net.inet6.ip6.auto_linklocal: 1 -> 0
DHCPREQUEST on npe0 to 255.255.255.255 port 67
ip length 328 disagrees with bytes received 332.
accepting packet with data after udp payload.
DHCPACK from 10.0.0.1
bound to 10.0.0.12 -- renewal in 900 seconds.
lo0: flags=8049 metric 0 mtu 16384
inet6 fe80::1%lo0 prefixlen 64 scopeid 0x2
inet6 ::1 prefixlen 128
inet 127.0.0.1 netmask 0xff000000
npe0: flags=8843 metric 0 mtu 1500
ether 00:14:bf:68:47:ba
inet6 fe80::214:bfff:fe68:47ba%npe0 prefixlen 64 scopeid 0x1
inet 10.0.0.12 netmask 0xffffff00 broadcast 10.0.0.255
media: Ethernet autoselect (100baseTX )
status: active
Additional routing options:.
Starting devd.
Additional IP options:.
Mounting NFS file systems:.
Creating and/or trimming log files:.
Starting syslogd.
/etc/rc: WARNING: Dump device does not exist. Savecore not run.
ELF ldconfig path: /lib /usr/lib /usr/lib/compat
Initial arm initialization:.
Additional ABI support:.
Clearing /tmp (X related).
Starting local daemons:.
Updating motd.
Mounting late file systems:.
Starting cron.
Local package initialization:.
Starting inetd.
Starting background file system checks in 60 seconds.

Thu Jan 1 00:00:39 UTC 1970

FreeBSD/arm (slug) (ttyu0)

login: root
Jan 1 00:03:24 slug login: ROOT LOGIN (root) ON ttyu0
Last login: Thu Jan 1 00:42:28 on ttyu0
Copyright (c) 1992-2008 The FreeBSD Project.
Copyright (c) 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994
The Regents of the University of California. All rights reserved.

FreeBSD 8.0-CURRENT (NSLU) #12: Sun Aug 3 00:09:07 MDT 2008

Welcome to FreeBSD!

Before seeking technical support, please use the following resources:

o Security advisories and updated errata information for all releases are
at http://www.FreeBSD.org/releases/ - always consult the ERRATA section
for your release first as it's updated frequently.

o The Handbook and FAQ documents are at http://www.FreeBSD.org/ and,
along with the mailing lists, can be searched by going to
http://www.FreeBSD.org/search/. If the doc distribution has
been installed, they're also available formatted in /usr/share/doc.

If you still have a question or problem, please take the output of
`uname -a', along with any relevant error messages, and email it
as a question to the [email protected] mailing list. If you are
unfamiliar with FreeBSD's directory layout, please refer to the hier(7)
manual page. If you are not familiar with manual pages, type `man man'.

You may also use sysinstall(8) to re-enter the installation and
configuration utility. Edit /etc/motd to change this login announcement.

nslug# ntpdate harmony
3 Aug 07:04:18 ntpdate[582]: step time server 10.0.0.6 offset 1217746845.716155 sec
slug# date
Sun Aug 3 07:04:19 UTC 2008
slug# df
Filesystem 1K-blocks Used Avail Capacity Mounted on
10.0.0.8:/pe/slug 55871592 49741636 1660230 97% /
devfs 1 1 0 100% /dev
10.0.0.8:/pe 55871592 49741636 1660230 97% /pe