[lkml]   [2007]   [Nov]   [22]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
Messages in this thread
    Subject[RFC] Documentation about unaligned memory access
    Being spoilt by the luxuries of i386/x86_64 I've never really had a good
    grasp on unaligned memory access problems on other architectures and decided
    it was time to figure it out. As a result I've written this documentation
    which I plan to submit for inclusion as

    Before I do so, any comments on the following?



    Linux runs on a wide variety of architectures which have varying behaviour
    when it comes to memory access. This document presents some details about
    unaligned accesses, why you need to write code that doesn't cause them,
    and how to write such code!

    What's the definition of an unaligned access?

    Unaligned memory accesses occur when you try to read N bytes of data starting
    from an address that is not evenly divisible by N (i.e. addr % N != 0).
    For example, reading 4 bytes of data from address 0x10000004 is fine, but
    reading 4 bytes of data from address 0x10000005 would be an unaligned memory

    Why unaligned access is bad

    Most architectures are unable to perform unaligned memory accesses. Any
    unaligned access causes a processor exception.

    Some architectures have an exception handler implemented in the kernel which
    corrects the memory access, but this is very expensive and is not true for
    all architectures. You cannot rely on the exception handler to correct your
    memory accesses.

    In summary: if your code causes unaligned memory accesses to happen, your code
    will not work on some platforms, and will perform *very* badly on others.

    You may be wondering why you have never seen these problems on your own
    architecture. Some architectures (such as i386 and x86_64) do not have this
    limitation, but nevertheless it is important for you to write portable code
    that works everywhere.

    Natural alignment

    The rule we mentioned earlier forms what we refer to as natural alignment:
    When accessing N bytes of memory, the base memory address must be evenly
    divisible by N, i.e. addr % N == 0

    When writing code, assume the target architecture has natural alignment

    Sidenote: in reality, only a few architectures require natural alignment
    on all sizes of memory access. However, again we must consider ALL supported
    architectures; natural alignment is the only way to achieve full portability.

    Code that doesn't cause unaligned access

    At first, the concepts above may seem a little hard to relate to actual
    coding practice. After all, you don't have a great deal of control over
    memory addresses of certain variables, etc.

    Fortunately things are not too complex, as in most cases, the compiler
    ensures that things will work for you. For example, take the following

    struct foo {
    u16 field1;
    u32 field2;
    u8 field3;

    Let us assume that an instance of the above structure resides in memory
    starting at address 0x10000000. With a basic level of understanding, it would
    not be unreasonable to expect that accessing field2 would cause an unaligned
    access. You'd be expecting field2 to be located at offset 2 bytes into the
    structure, i.e. address 0x10000002, but that address is not evenly divisible
    by 4 (remember, we're reading a 4 byte value here).

    Fortunately, the compiler understands the alignment constraints, so in the
    above case it would insert 2 bytes of padding inbetween field1 and field2.
    Therefore, for standard structure types you can always rely on the compiler
    to pad structures so that accesses to fields are suitably aligned (assuming
    you do not cast the field to a type of different length).

    Similarly, you can also rely on the compiler to align variables and function
    parameters to a naturally aligned scheme, based on the size of the type of
    the variable.

    Sidenote: in the above example, you may wish to reorder the fields in the
    above structure so that the overall structure uses less memory. For example,
    moving field3 to sit inbetween field1 and field2 (where the padding is
    inserted) would shrink the overall structure by 1 byte:

    struct foo {
    u16 field1;
    u8 field3;
    u32 field2;

    Sidenote: it should be obvious by now, but in case it is not, accessing a
    single byte (u8 or char) can never cause an unaligned access, because all
    memory addresses are evenly divisible by 1.

    Code that causes unaligned access

    With the above in mind, let's move onto a real life example of a function
    that can cause an unaligned memory access. The following function adapted
    from include/linux/etherdevice.h is an optimized routine to compare two
    ethernet MAC addresses for equality.

    unsigned int compare_ether_addr(const u8 *addr1, const u8 *addr2)
    const u16 *a = (const u16 *) addr1;
    const u16 *b = (const u16 *) addr2;
    return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2])) != 0;

    In the above function, the reference to a[0] causes 2 bytes (16 bits) to
    be read from memory starting at address addr1. Think about what would happen
    if addr1 was an odd address, such as 0x10000003. (Hint: it'd be an unaligned

    Despite the potential unaligned access problems with the above function, it
    is included in the kernel anyway but is documented to only work on
    16-bit-aligned addresses. It is up to the caller to ensure this alignment or
    not use this function at all. This alignment-unsafe function is still useful
    as it is a decent optimization for the cases when you can ensure alignment.

    Here is another example of code that could cause unaligned accesses:
    void myfunc(u8 *data, u32 value)
    *((u32 *) data) = cpu_to_le32(value);

    This code will cause unaligned accesses every time the data parameter points
    to an address that is not evenly divisible by 4.

    Consider the following structure:
    struct foo {
    u16 field1;
    u32 field2;
    u8 field3;
    } __attribute__((packed));

    It's the same structure as we looked at earlier, but the packed attribute has
    been added. This attribute ensures that the compiler never inserts any padding
    and the structure is laid out in memory exactly as is suggested above.

    The packed attribute is useful when you want to use a C struct to represent
    some data that comes in a fixed arrangement 'off the wire'.

    It should be clear why accessing fields of an instance of that structure could
    cause unaligned accesses in some situations. Even if the instance started at
    an address such as 0x10000000 where accessing field1 would not cause an
    unaligned access, accessing field2 would be reading 4 bytes from 0x10000002,
    which, is an unaligned access. The compiler didn't jump to your rescue and
    insert padding because you asked it not to.

    In summary, the 3 main scenarios where you may run into unaligned access
    problems involve:
    1. Recasting variables to types of different lengths
    2. Pointer arithmetic followed by access to at least 2 bytes of data
    3. Accessing elements of packed structures

    Avoiding unaligned accesses

    Going back to an earlier example:
    void myfunc(u8 *data, u32 value)
    *((u16 *) data) = cpu_to_le32(value);

    To avoid the unaligned memory access, you could rewrite it as follows:

    void myfunc(u8 *data, u32 value)
    value = cpu_to_le32(value);
    memcpy(data, value, sizeof(value));

    It's safe to assume that memcpy will always copy bytewise and hence will
    never cause an unaligned access.

    Recall an example packed structure from earlier:

    struct foo {
    u16 field1;
    u32 field2;
    u8 field3;
    } __attribute__((packed));

    The following code will potentially cause 2 unaligned accesses: writing to
    field2, then reading from field2:

    void myfunc2(u32 some_data)
    struct foo myinstance;
    u32 tmp;

    myinstance.field2 = some_data;
    tmp = myinstance.field2 * 2;

    When writing this code, you should be aware that field2 acccesses are
    potentially unaligned therefore the above will break on some systems. The
    kernel provides two macros to simplify handling of situations such as the

    void myfunc2(u32 some_data)
    struct foo myinstance;
    u32 tmp;

    put_unaligned(tmp, &myinstance.field2);
    tmp = get_unaligned(&myinstance.field2);

    These macros work from pointers to the unaligned data, and work for memory
    accesses of any length (not just 32 bits as in the example above). You could
    even use put_unaligned() rather than memcpy() in order to solve the bug in
    the first example (myfunc()) given above.

    Author: Daniel Drake <>
    With help from: Johannes Berg, Uli Kunitz.

    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to
    More majordomo info at
    Please read the FAQ at

     \ /
      Last update: 2007-11-23 01:19    [W:0.033 / U:0.272 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site