Unhandled fault: alignment fault (0x92000061) at 0x00000000fff0f729


I have an arm cortex A-57 machine that is running 3.16 linux kernel (64bit) compiled using gcc-linaro-aarch64_be-linux-gnu-4.9-2014.09_linux toolchain.

My application (32bit) is accessing a member inside a structure at unaligned address using pointer (type casted). The application is compiled using gcc-linaro-armeb-linux-gnueabihf-4.9-2014.09_linux toolchain and when its run, the application gets bus error with "Unhandled fault: alignment fault (0x92000061) at 0x00000000fff0f729" on console.

I have tried compiling the application using the gcc-linaro-armeb-linux-gnueabihf-4.9-2014.09_linux toolchain with compile flags -mno-unaligned-access and again with -munaligned-access flags. I see alignment fault in both the cases.

I looked at the linux kernel sources and understood that, arm64 linux kernel doesn't implement fix-up routine to address the un-aligned access, where-as arm32 linux kernel implements a fix-up routine to fix the un-aligned access.

Could someone help to provide a patch that implements un-aligned access fix-up for arm64 linux kernel?

arm32 linux kernel alignment fault exception handling is implemented using assembly code and requires knowledge on arm instruction set details. Though I could get some information on decoding instruction, I still couldn't figure out full internals. Is there a pseudo code or set of steps to fix-up un-aligned access issue on ARM64?

Thanks & Regards,

  • There shouldn't be a need for any special code to handle this, there is a bit in the system control register SCTLR A which defaults to 0 meaning disable alignment check. This affects all usual instruction except for some things like LDRD/STRD, LDM/STM plus some Neon and exclusive access instructions. The big exception is that it only does this for access to normal memory i.e. memory that can be cached rather than device memory. You're not somehow accessing memory for an I/O device are you? Knowing what instruction caused the problem might help.
  • The compiler will assume that a pointer is correctly aligned for the type (e.g. a pointer to a 32-bit type will be aligned to a 32-bit boundary). If you cast a pointer then it assumes you know what you are doing, and that the resultant pointer will be correctly aligned.

    So for example:

    int8 byte;
    int32* word = &byte;

    Is unsafe, as the resulting pointer is probably not word aligned but you've "promised" the compiler it is.

    The problem this can cause is that not all instructions can perform unaligned accesses. For example, LDM/STM can never be unaligned. As the compiler doesn't know the pointer is unaligned, it doesn't know not to use these instructions.

    The ARM Compiler (armcc) had the __packed keyword to get around this.

    __packed uint32* pWord;

    Told armcc that the pointer might unaligned and hence not use instructions which couldn't handle unaligned addresses. I don't believe that GCC has a direct equivalent (it does for structs), but could be wrong.