These pages describe the parts of the Alpha architecture that most often cause problems when software is first built for Alpha/Linux.
Many of these failures are latent defects in portable code rather than Alpha-specific problems. Alpha traps on every misaligned load or store other than LDQ_U and STQ_U, does not order dependent loads, and reports arithmetic traps imprecisely on processors before the 21264; the original architecture also had no byte or word stores. Alpha therefore exposes defects that x86 tolerates. Where that is the case, these pages cite the evidence that a change is a genuine fix rather than an architecture-specific workaround.
| Page | Topic |
|---|---|
| Unaligned Access | Why *(uint32_t *)(buf + 1) is undefined behavior in C, how it also crashes x86 programs, and how to find and fix it |
| Byte and Word Access | The byte/word extension (BWX), pre-BWX byte and word access, and why non-atomic byte access ended pre-EV56 support |
| Memory Model | The weakest memory model Linux supports, dependent load reordering, barriers, and load-locked / store-conditional |
| Floating Point | -mieee, imprecise traps, software completion, the FPCR, and denormals |
| Why Alpha Has libc.so.6.1 | Code that names libc.so.6, and the January 1997 ABI break behind the different name |
| Linux ABI Differences | The 8 KiB page size, 128-bit long double, va_list, the 1024 Hz clock tick, and the system call, errno, signal, and ioctl numbers that differ from x86-64 |
| Symptom | Likely cause | Page |
|---|---|---|
unaligned trap messages in the kernel log, or SIGBUS | A misaligned load or store, or a misaligned atomic operation | Unaligned Access |
SIGFPE on floating-point code, often on NaN, infinity, or denormal operands | Code built without -mieee | Floating Point |
SIGILL | Code built for a newer processor (-mcpu) than the one running it | Toolchains |
| Corrupted neighboring bytes under threads or signals | Non-atomic byte or word stores in code built for pre-EV56 processors | Byte and Word Access |
| Intermittent failures in lock-free code | Missing memory barriers | Memory Model |
libc.so.6: cannot open shared object file | The C library named by file name | Why Alpha Has libc.so.6.1 |
Wrong errno values, signals, or ioctl requests; EINVAL from mmap() | Numbers copied from x86, or a 4 KiB page size assumed | Linux ABI Differences |
CPU times from times() or /proc about ten times too large | Clock ticks assumed to be 100 per second | Linux ABI Differences |
conversion … to non-scalar type __gnuc_va_list at compile time | A va_list treated as a pointer | Linux ABI Differences |
relocation truncated to fit at link time | GOT or small data area overflow | Toolchains |
-mcpu=ev56, Gentoo's to the architecture baseline. Gentoo's release stages are built with -mcpu=ev4, so the code in them stores bytes and words with non-atomic pre-BWX sequences (see Byte and Word Access). 1) 2) See Distribution baselines.-mieee. Debian and Gentoo enable it by default; upstream GCC does not. Code that handles NaN, infinity, or denormals needs it. See Floating Point.sysconf(_SC_PAGESIZE). See Page size.SIGBUS. See Unaligned Access.imb PALcode call after writing code and before running it (see PALcode calls), change page protections in 8 KiB units (see Page size), set up $27 and $29 as the calling convention requires (see Registers), implement or call integer division, and assemble for EV56 or later so that byte stores are atomic (see binutils).libc.so.6.1, packaged in Debian as libc6.1 and libc6.1-dev rather than libc6 and libc6-dev. See Why Alpha Has libc.so.6.1.alpha-unknown-linux-gnu (alpha-linux-gnu on Debian). Processor-specific triplets such as alphaev67-unknown-linux-gnu are also valid, so configure scripts should match alpha*. 3) config.guess run on an Alpha returns such a triplet itself, taking the processor from the cpu model line of /proc/cpuinfo: alphaev67-unknown-linux-gnu on an EV67, for example. 4) Meson's CPU family for Alpha is alpha, which it counts as a 64-bit family. 5) 6)The predefined macros show which processor and floating-point mode a compiler targets, including defaults that a distribution builds into it:
gcc -dM -E - </dev/null | grep -E '__alpha_|_IEEE_FP'
GCC defines __alpha_bwx__, __alpha_max__, __alpha_fix__, and __alpha_cix__ for each enabled extension, one of __alpha_ev4__, __alpha_ev5__, or __alpha_ev6__ for the scheduling family, _IEEE_FP under -mieee, and _IEEE_FP_INEXACT under -mieee-with-inexact. 7) Output with no __alpha_bwx__ means that byte and word stores are compiled as non-atomic pre-BWX sequences. gcc -Q –help=target lists the Alpha options and the values in effect, such as -mcpu= and -mieee.
objdump -d shows how a binary was compiled. Floating-point instructions with a /su or /sui suffix (addt/su) come from -mieee or -mieee-with-inexact, as do trapb barriers in code built for processors before the EV6 (see Trap shadows); a /d suffix from -mfp-rounding-mode=d. stb and stw instructions mean the code was built for BWX; byte stores built without it appear as ldq_u, mskbl, insbl, stq_u sequences.
LD_SHOW_AUXV=1 makes the dynamic linker print the auxiliary vector before running any program: HWCAP holds the extension bits described in Architecture Mask, PLATFORM the kernel's processor class (ev56, ev6, or ev67), and CLKTCK the 1024 Hz clock tick. 8) 9)
LD_SHOW_AUXV=1 /bin/true
qemu-alpha runs Alpha programs on another host, which is enough to find build failures, wrong constants, and most ABI problems. It does not reproduce everything real hardware does:
SIGBUS with prctl(PR_SET_UNALIGN). 10) 11) They have to be found on hardware or with the methods in Finding unaligned accesses.-cpu; the default, EV67, runs code that would raise SIGILL on an EV56.Alpha documentation calls a 16-bit quantity a word, a 32-bit quantity a longword, and a 64-bit quantity a quadword. These pages follow that usage.