The latest version of this page should be available at http://skarpsey.dyndns.org/alpha-lfs/alpha.html. The patches mentioned on this page should be available at http://skarpsey.dyndns.org/alpha-lfs/patches/.
A great many hobbyists like the idea of running Linux on the Alpha platform. If you don't know about the Alpha platform, you probably don't even need to be here.
There are many options for running Linux on Alpha. One of the most common options is to get a distribution that's been ported to the Alpha, such as Debian, RedHat, SuSE, etc. and rely entirely on that distribution's precompiled packages. This is theoretically the safe route. If you plan to hold strictly to this route, you probably don't need to be here.
The other option is to compile all or part of your Linux installation from source code. Since Linux is open-source, it lends itself reasonably well to this approach, and it gives the user a lot more power over how software gets installed. This is the fun route (for some of us anyways ;) ).
Alas, there are problems with the "fun" approach. The biggest problem is that many open-source applications are not quite ported or are not well tested on the Alpha platform. Most problems spring from source code not being 64-bit clean--since the developers often have only a simple x86 system to work on, they may not have the time or opportunity to make sure their code works on anything else. In any case, since the x86 platform is becoming the most prevalent platform in existence, software generally tends to be more stable or better optimized on x86 than on Alpha.
This page is one of the many efforts to correct this. Despite the problems getting software to compile on the Alpha, there are actually many Alpha-specific fixes that already exist, and others that just take a little bit of work to create. It simply makes it easier if everyone has a fairly centralized repository for such fixes, so Alpha owners don't have to scour the 'net so much for solutions.
From alt.sysadmin.recovery:
"Best viewed with Netscape 4.7 for UNIX/X on a 1280x1024 resolution with 24-bit color depth, maximum contrast, minimum brightness, in a 1000x960 window placed in the exact center of your display with this window manager configuration [etc.]" -- Unknown
"...with a colour temperature of 9300K using barco phosphors and connected to an AGP Matrox G200 via 5 individual RG179B/U coax cables with a contact resistance less than 0.1 mOhm..." -- David Jordan
"On an <insert impossible to find make of monitor> here." -- Peter Corlett
"Monitor? I was thinking along the lines of a UKP 10k data projector placed 3142mm from a 2m diagonal screen in a semiconductor clean room with no more than 5 10um particles per cubic metre of air...
Nah... That's going too far... What you want to say is, 'Don't look at this page, it's crap.'" -- David Jordan
Hmph. Any browser should work fine. Hell, Lynx on an 80x25 terminal works fine.
Some time ago (Oct/Nov 2002), I was fortunate enough to obtain a reasonably powerful Alpha box--a slightly gutted Durango II (an old OEM box manufactured by Aspen Systems) containing a working 21164A (EV56) clocked at 600MHz. The system is reasonably ATX compliant, so just about everything except the motherboard and processor can be replaced with inexpensive commodity parts. If you wish to build an Alpha system of your own on a hobbyist's budget, this is probably a good combination to start with.
One of the first things I did with the system (after I installed a hard drive) was to commence compiling a Linux distribution from scratch. If you're interested in how to do this yourself, you can simply check out the Linux from Scratch project. So far, my work is going well, though not quite as fast as I had hoped. I'm still working to turn this Alpha box into a respectable Linux workstation.
In the process of compiling software, I found many packages that needed fixing to run on the Alpha. Some fixes I came up with on my own; others were simply out there on the 'net and were discovered through laborious searching. I decided it would be nice if I could save other people some work...
If you find something that you think ought to go on this page, feel free to e-mail me. I can't promise I'll post every fix here, but I'll try to evaluate each one I can.
If you've found some Linux bug that you think may be related to Alpha compatibility, you can contact me, and I might be willing to investigate it. I've actually churned out a great many Alpha-related patches for my own use (I proactively audit certain compiler warnings these days); I just don't always post them unless I'm sure they actually fix something. So if your Linux software is mysteriously misbehaving on the Alpha, I might already know some trick that could save your bacon.
The LinuxFromScratch project -- guides you through the trials of compiling an entire Linux distribution from source.
The AlphaLinux website -- another central resource for those wishing to run Linux on the Alpha platform. It's more generalized than this page, however.
HP's Alpha web site -- Alpha resources, straight from HP (the current maintainer of the Alpha platform). Sadly, HP is putting the Alpha platform to sleep sometime in 2004. =(
Greg Schafer's LFS tweaks -- somewhat related to this site, but limited to toolchain (gcc, glibc, binutils) fixes which apply to all platforms. His fixes and mine can (usually) be mixed together without problems.
I take no responsibility for damage resulting from the use or misuse of these tweaks. Generally they "work for me", but this is no guarantee that they will work for you. If one or more of these tweaks breaks your box, I will not accept any sort of liability for that. Use these tweaks at your own risk. ;)
That being said, if someone finds a tweak or fix that is somehow in error, I will do my best to fix the error, or at the very least warn people about possible breakage. Feel free to notify me about any problems.
glibc-2.2.5 "divrem" fix (optional build fix)
Recent versions of the GNU toolchain may have trouble compiling glibc at all. The problem can be fixed with this patch for glibc. Find out more about the problem here.
This problem is fixed in glibc-2.3.1.
glibc-2.2.5 "pthread_setspecific" fix (critical build fix)
Versions of gcc >=3.1 will optimize away a certain critical function call in glibc, causing the pthread_setspecific() function to segfault. This very ugly problem can be fixed with this patch for glibc. Find out more about the problem here.
This problem is fixed in glibc-2.3.1.
aboot-0.9a "puts" hack (optional build fix)
Recent versions of the GNU toolchain may have trouble compiling aboot at all. I'm not exactly sure why this happens, but it has to do with the puts() function getting linked to the bootloader code. Because puts() depends on kernel services (and the kernel isn't even up when the bootloader runs), the bootloader cannot call upon it--during compilation, the problem will get noticed as an unresolved reference to the puts() function, and the build will punt. In order to work around the problem, I created this patch. It allows aboot to compile and run normally, but it will probably prevent it from compiling in "TESTING" mode (a mode I gather is useful only to those who hack on aboot).
This problem is fixed in aboot-0.9b.
findutils-4.1 "_GNU_SOURCE" fix (critical build fix)
findutils-4.1 isn't quite 64-bit clean. I traced the problem to a function prototype in string.h that doesn't get declared unless the macro _GNU_SOURCE is defined. gcc issues an "implicit declaration" warning about it during compilation and stupidly assumes the function returns a 32-bit int when it really returns a pointer. This doesn't hurt platforms where pointers are 32-bit (like x86), but it causes the "find" utility to segfault on platforms where pointers are 64-bit (like Alpha).
The solution is to set CPPFLAGS="-D_GNU_SOURCE" in your environment before compiling findutils.
XFree86-4.2.x "gprel" fix (critical build fix)
Versions of gcc >=3.1 add two new ELF relocatable symbol types relating specifically to the Alpha platform. Normally, this wouldn't be a problem, as common applications don't care about "ELF relocatable" format files (these are your basic .o object files produced as an intermediate step when building a binary). However, XFree86 by default expects its modules to be in "ELF relocatable" format and thus requires direct knowledge of this file format. As a result, when compiled with a recent gcc version, XFree86 4.2.x will build but will then be unable to load modules--it will complain about unsupported ELF relocation types 17 and 18.
The solution is to apply this patch to XFree86, initially developed by Thorsten Kraznowski and contributed to XFree86-CVS.
This problem is fixed in XFree86 4.3.0.
netkit-base-0.17 "ping" hack (essential build fix)
The netkit-base-0.17 "ping" utility doesn't work well on Alpha platforms. On my Alpha box, it was able to ping itself and get a reply, but it wasn't able to ping any other box on my network.
The quick solution for netkit-base is to apply this patch, taken from Gentoo CVS. The better solution is to switch to GNU inetutils; netkit as a whole is largely unmaintained and has many other problems working on an Alpha.
linux-2.4 "core_cia" patch (kernel bugfix)
Older revisions of the EB164 motherboard (predecessor to the PC164 series motherboards) have a bug in PCI DMA handling. This may cause intermittent PCI errors or even complete boot failure. This patch works around the problem by reverting the kernel to an old behavior that doesn't trip over this bug. Thanks go to Sebastiaan Pais for bringing this issue to my attention.
Alternatively, you may try this patch. It does about the same thing as the first patch, but also implements a run-time check to see if the workaround is necessary.
kde-3.0.5a "strlcpy" patches (build fix)
KDE 3.0.5a was released to cover a far-reaching set of security vulnerabilities involving the way KDE handles quotes. Unfortunately, in the rush to make a fixed release available, a certain ./configure check was introduced in many KDE packages that fails on the Alpha.
The problem in this case is pretty trivial to fix. The check was necessary only to cover for a rather ugly hack; once the ugly hack is moved out of the way, the check can safely be dispensed with. The following patches take care of it for their respective packages:
kdebase-3.0.5a-strlcpy.patch
kdenetwork-3.0.5a-strlcpy.patch
kdepim-3.0.5a-strlcpy.patch
kdeutils-3.0.5a-strlcpy.patch
It should be noted, though, that the patches alter the ./configure scripts without altering the autoconf source files. You shouldn't have to worry about this unless you want to regenerate the ./configure scripts for some reason. Also, since the patches are more of a quick-hack solution, they don't actually wipe the output from the configure test--the ./configure scripts will simply say the relevant test passed, even though it would probably fail if it was actually run. This bit of oddness can safely be ignored.
This problem is fixed in KDE 3.1.
universal "gp-relative relocation" fix (general build fix)
Occasionally, you may see the following error when linking shared objects (dynamic libraries) on Alpha:
gp-relative relocation against dynamic symbol xxxxxx
This happens because by default, most Alpha gcc versions calculate variable addresses as offsets against an internal register in the Alpha CPU. This generally doesn't cause a problem with binaries, but it's a major problem for shared objects--thus recent binutils versions will refuse to link shared objects if they spot this problem in the object files. The good-and-proper fix is to compile the code with -fpic or -fPIC in your CFLAGS. This instructs the compiler to generate "position-independent code" and avoid this problem.
Occasionally, the problem will not be in the source code you're trying to compile, but in a completely different package. Sometimes a package will try to build a shared object by linking a static library (.a file) from a different package, and static libraries are usually not compiled with -fPIC. In this case, the error messages will tell you exactly which static libraries contain gp-relative relocations. The only solution is to find what package provides these static libraries and recompile that package with -fPIC.
Really, when building shared objects on any platform, it's good practice to use the -fPIC flag. The GNU/x86 toolchain won't complain if -fPIC is omitted, but the GNU toolchain will punt on most other platforms.
lcms "va_list" fix (build fix)
lcms-1.09 includes optional utilities (tifficc and jpegicc) for applying ICC profiles to TIFF or JPEG files. Unfortunately, the jpegicc source code makes the assumption that the va_list data type (from stdarg.h) can be assigned a value of NULL. This assumption is valid on gcc/i386, but not on gcc/alpha; it causes "make jpegicc" or "make utils" to fail with the following output:
jpegicc.c: In function `my_output_message': jpegicc.c:139: incompatible type for argument 3 of `ConsoleWarningHandler'
You can find a usable workaround patch here. The maintainer of lcms is currently on sabbatical and probably won't answer any e-mails at the moment. He should be back in May 2003, at which time I will notify him of this issue.
UPDATE 20030518:lcms-1.10 has been released, and it has the same bug. However, it requires a different patch. I've notified the maintainer(s) of the issue, so we'll see what happens next.
UPDATE 20030525: As of May 19, the patch is being incorporated into the official lcms sources.
mozilla-1.3 "alpha stubs" fix (build fix)
Mozilla on alpha follows a strange practice of accessing certain C++ function stubs directly via ugly little bits of assembly code. One of the major downsides of this approach is that the developers must know exactly how C++ function names get mangled. The stock Mozilla source code can grok the C++ name mangling in gcc 2.x, but gcc 3.x implements a new name mangling scheme that Mozilla doesn't know about. This results in undefined references to "StubXXX()" functions during the link phase.
I would think that this stumbling block would be enough to dissuade the use of such a nauseating little hack, but the Mozilla developers think differently. So...in the meantime, we can apply this patch to make Mozilla aware of the new name mangling conventions. It was developed primarily by Glen Nakamura, the developer initially responsible for much of Mozilla's alpha-specific bits. It works with Mozilla 1.3 and should work with earlier Mozilla versions as well.
binutils-2.13.2.1 "GPREL32" (toolchain fix)
Occasionally, you may get the following error message when compiling software on Alpha:
relocation truncated to fit: GPREL32 *UND*
Most notably, this affects kdegames-3.1.x.
This is caused by a long-standing bug in the GNU Linux-Alpha toolchain. Certain symbols (such as switch-related jump tables in inline C/C++ functions) cause gcc to emit object relocations leading to removed ELF sections, and until recently, binutils did not know how to handle this. You can learn more about this issue here.
This can be fixed via this patch to binutils, contributed by Richard Henderson. Expect binutils to include this fix in all official versions after 2.13.2.1. Unofficial versions (such as H.J. Lu's binutils fork) may include the fix even sooner.
SGI XFS deadlock (kernel fix)
People running a recent version of SGI XFS on Alpha (say, release 1.2 or later) may notice processes getting stuck in 'D' state. 'D' state is an unkillable I/O state; it's perfectly normal for a process to enter 'D' state when the kernel is doing I/O on its behalf, but it's not normal for the process to stay in 'D' state forever.
This problem apparently occurs on Alpha because the XFS driver makes an assumption about sizeof(long) and then tries to clamp a value based on that assumption. Find out more about the issue here; get the necessary patch here and apply it to your kernel source tree after applying the XFS patchset.
This patch was contributed by Yours Truly(tm) and revised by Steve Lord. It was merged with XFS-CVS on May 1 2003.
UPDATE 20030505: seems that patch isn't a complete fix. I'm still running into deadlocks; they're just a lot less frequent with the patch. I will provide more info as I have it.
UPDATE 20030517: well, no further patching is needed for the kernel, it seems. However, if you've been bitten by the bug, you may have to clean up some latent damage to the affected filesystem before deadlocks go away. mkfs.xfs is the sure-fire way to do it; xfs_repair may work also. fsck.xfs doesn't seem to notice the damage.
lm_sensors-2.8.0 alpha fixes (build fix)
i2c-2.8.0 and lm_sensors-2.8.0 have (mostly minor) issues when building on Alpha. This patch fixes i2c-2.8.0; this patch fixes most of lm_sensors-2.8.0. Unfortunately, the i2c-tsunami driver in lm_sensors-2.8.0 is in a nonworking state, and all I could do with that driver is disable building it for now. I may have a better solution later.
Most of this work is done by me, except for the i2c-elektor fixes, which were done by Oleg Vdovikin. The patches were posted to the lm_sensors mailing list on July 2003 and will probably be merged into lm_sensors CVS.
On Alpha, IEEE compliance, and software floating-point (optimization tweak)
Every once in a while, an Alpha newbie pops up with his first Alpha box on an Alpha-centric forum. One of the typical first questions he may ask is about this GCC option called -mieee, what exactly it does, and what the heck a renowned floating-point workhorse like the Alpha is doing needing "software floating-point completion." (Hey, I was once such a newbie. So sue me.)
Well, it's a long story.
First of all, it's traditional for C/C++ source code to be able to base calculations on indeterminate quantities and division by zero, and actually expect consistent, useful results. In real life this sounds strange--computers aren't supposed to be able to divide by zero--but such operations have a purpose and a definite pattern in the more abstract, theoretical branches of mathematics.
There's a standard called IEEE754 that's supposed to outline how a computer should represent floating-point numbers internally, how it's supposed to represent "invalid" results and infinite quantities, and how it's supposed to handle the strange cases like floating-point division by zero.
Quite simply, a floating-point divide-by-zero is supposed to produce either NaN ("Not a Number"), infinity, or negative infinity, depending on what all the inputs are. In ANSI C/C++, these quantities are represented by the macros NAN, HUGE_VAL, and -HUGE_VAL, respectively. Floating-point operations using infinity or negative infinity as one of the inputs are also supposed to produce usable, predictable results.
In addition, there are cases where a floating-point operation may produce an infinitesimal quantity rather than an infinite quantity--a quantity that is extremely close to (but not quite) zero. The problem with this is that the IEEE754 floating-point format has only a limited precision, and sometimes that precision is not enough to distinguish between an infinitesimal quantity and zero. Obviously the sensible thing to do is to represent the quantity as zero and be done with it.
The problem with the above cases (division by zero, positive or negative infinity, and infinitesimal quantities) is that they take a little extra work on the part of a floating-point unit. Alphas prior to the EV6 (21264) generation fudged this a bit; essentially an Alpha processor prior to EV6 needs the software to lend a helping hand in order to reliably and predictably handle these special cases. In Linux, the "helping hand" consists of special kernel handling of FPU exceptions, plus special instructions inserted in userland code. These measures allow the software to transparently recover from floating-point exceptions triggered by these special cases and essentially emulate that little bit of functionality the early Alpha processors lacked.
This process is known as "software floating-point completion." It sounds horrible primarily to those who remember days of running x86 hardware with floating-point operations handled purely in software--floating-point performance suffered severely in such cases. Don't worry, software FP completion on Alpha isn't nearly as horrid as that.
Enabling this software FP completion is generally not a problem. The first step involves enabling "Kernel FP software completion" (CONFIG_MATHEMU) in your Linux kernel configuration. On kernel 2.4.21, this is under the "Kernel hacking" menu. You may have to turn on "Kernel debugging" to see it in menuconfig or xconfig.
Once software FP completion is enabled in the kernel, you can enable the userland support on an application-by-application basis. Simply pass the "-mieee" option to gcc whenever compiling a source file. This causes gcc to generate the necessary instruction sequences. There's a catch, though; if you want an application to have full support for software FP completion at all points of execution, then any library or object file that application links with will also need to be compiled with -mieee. Building an application with -mieee will make the application's internal code support software FP completion, but it does not cover routines in external libraries the application links to. You may find yourself having to recompile a great many libraries just to make your application work!
Now, for a little FAQ on the issue:
Q) What happens if software FP completion isn't enabled?
A) If the application tries to work with the "special" IEEE754 quantities without having software FP completion enabled, it will receive a SIGFPE ("floating-point exception" signal). This typically causes an application to immediately exit with an error code of 136, after printing out "Floating point exception" on the standard error stream.
Q) How much of a performance hit does this cause?
This generally causes less than a 5% performance hit. There are some math-intensive applications where it might cause a greater performance hit; however, in these math-intensive applications, it's usually a question of enabling floating-point completion, or simply having the app be unstable or completely nonworking. So it's generally a Good Idea(tm) to enable software FP completion in all cases. It will probably save you enough troubleshooting time to make up for any lost execution time by far.
Q) You said only pre-EV6 processors need this. Is it harmful on EV6 or later?
A) Typically not. For EV6 or later, the kernel-land code just won't be activated, and the extra instructions inserted in user-land code will simply be discarded as NOP ("no operation") instructions early in the processor's pipeline. The code footprint will remain a little bloated from the extra instructions, and the early stages of the processor's pipeline might get occupied a bit more, but this is generally negligible.
On the other hand, though, if you're coding purely for EV6 or later, there's no point in enabling software FP completion either.
Q) If using this is recommended in almost all cases, why isn't -mieee the default?
A) Well...we're working on that. A few people have floated some gcc patches to make -mieee the default option, but none have yet been accepted by the gcc developers. You can find out more about this by searching the Debian-Alpha mailing list (debian dash alpha at lists dot debian dot org). This topic seems to come up every few weeks there.
fluxbox-0.9.5 "resize" fix (build fix)
fluxbox-0.9.5 has trouble compiling on Alpha, due to a prototoype mismatch between a function declaration and its corresponding definition. Specificall, the FbRun::resize() method is declared with unsigned int parameters, then later defined with size_t parameters. This doesn't break x86 because on x86, size_t and unsigned int are coincidentally identical types. Alpha is not so lucky.
This patch fixes the issue. It was contributed to the fluxbox developers and merged into fluxbox CVS at the time of this writing.
kdemultimedia-3.1.4 "__u64" fix (build fix)
Hoo boy...this is going to take a while to explain.
Starting with kernel release 2.4.20 or somewhere thereabouts, the Linux kernel headers picked up a bug when reimplementing ___arch__swab64(). The bug primarily affects x86 platforms when code is compiled with gcc -ansi; it causes compilation to fail for any source file that includes <asm/byteorder.h> either directly or indirectly (through another dependent header such as <linux/cdrom.h>).
This bug bit kdemultimedia-3.1.3 in particular. So, for kdemultimedia-3.1.4, the KDE developers inserted a workaround by defining the __u64 type for itself. It doesn't actually use this type, it just defines it internally to keep <asm/byteorder.h> from breaking.
However, this kernel bug does not affect Alpha platforms, and on Alpha platforms, the workaround in kdemultimedia-3.1.4 causes the compile to fail in a different way. The most immediate solution to this problem is to remove the workaround; this patch takes care of that.
Note that the above patch is really only a workaround for a faulty workaround; it will break any platform where the original workaround is needed (i.e. an x86 box running kernel 2.4.21). A true fix might be for kdemultimedia to include its own "sanitized" kernel headers, or for the system to sport sanitized kernel headers of its own. The correct course of action for cases like this is currently rather undecided; my personal feeling is that the system should provide sanitized kernel headers of its own.
sysklogd-1.4.1 "query_modules" fix (bugfix)
klogd (from sysklogd-1.4.1) makes an effort to trace module symbols as part of its job, so it can possibly log any kernel-land bugs that get tripped and record what function or module tripped the bug. Ideally, you should have a System.map file matching the running kernel placed somewhere prominent on your system (/boot is a common and sensible location); klogd can use this file to get fully detailed information on what module symbol gets traced to where.
If klogd can't find a System.map file, it attempts to query the current list of modules and exported symbols from the running kernel. This is not ideal, as klogd is generally unable to get all the information it wants this way, but it is generally acceptable.
On many 64-bit platforms like the Alpha, klogd will segfault if forced to query modules in this manner. This stems from klogd trying to do a 64-bit file seek through /dev/kmem (a special device representing kernel memory that happens to contain the names and addresses of all module symbols). Due to limitations in the current Linux 2.4 VFS layer, lseek64() is unable to seek to extremely high 64-bit values, specifically any value above 0x7fffffffffffffff. This normally wouldn't be a problem, as most filesystems can't even support files this large anyways--but /dev/kmem is an exception. /dev/kmem is a special device file representing an image of the kernel's address space, which may very well occupy the full range of 64-bit numbers. In the case of the Alpha, the kernel maps module symbols to somewhere just under the top of its 64-bit address space, where nothing is able to reach via lseek64().
This limitation doesn't stop klogd from trying, though. Not only does klogd find itself unable to trace any module symbols, it leaves its data structures in such a mess internally that it eventually segfaults. In fact, if you run klogd with the "-n -d" options, you'll likely see something like this:
Logging line: Line: klogd %s.%s, log source = %s started. Priority: 6 Searching for symbol map. Trying /boot/System.map-2.4.21-2. Trying /boot/System.map. Trying /System.map-2.4.21-2. Trying /System.map. End of search list encountered. Logging line: Line: Cannot find map file. Priority: 4 Cannot find map file. Loading kernel module symbols - Size of table: 8 Error seeking in /dev/kmem Segmentation fault
What to do about this? Well, although this lseek64() limitation is really a kernel bug, it's a very rare corner-case kernel bug that would take a significant VFS rework to fix. The problem is more easily correctable in klogd.
klogd's method of tracing module symbols (seeking through /dev/kmem) is really a very antiquated hack. The kernel developers introduced a query_module() function long ago, so that tracing module symbols via /dev/kmem should no longer be necessary. So, in the name of progress, this patch updates klogd to use the newer query_module() function. It effectively dodges the lseek64() problem--and, incidentally, removes a possible race condition.
linux-2.4 system clock fix (kernel bugfix)
Recent Linux 2.4 kernels don't keep time all that accurately on Alpha. The kernel is responsible for the calibration and upkeep of the system clock, which typically keeps time by triggering an interrupt or similar event at regular intervals.
The kernel calculates a supposedly "exact" cycle frequency for the system clock based on the processor's internal frequency (700Mhz, 800MHz, etc.). It also calculates an "estimated" cycle frequency based on a fairly complicated and error-prone procedure. If the "estimated" cycle frequency is reasonably close to the "exact" cycle frequency, the exact frequency gets replaced with the estimated frequency (I have no idea why this is done. It makes no sense to me...)
Unfortunately, this can offset the "exact" frequency by as much as 1%, which can lead to a significant clock drift over time. The first, most obvious solution is to raise the bar for getting an "estimated" frequency accepted as exact. This patch takes care of that; it reduces the possible error from 1% to 0.1%. Credit for this patch goes to Michal Jaegermann of HardData.com.
Another possible solution is to simply not rely on the system clock to remain accurate on its own. Often it will stray; non-interruptible events like a kernel printk() occasionally leave the system clock missing a beat, no matter how accurately the frequency is calibrated. Use of NTP services can help the system clock stay on track.