Linux Kernel Architecture

(Jacob Rumans) #1
Mauerer runapp01.tex V1 - 09/04/2008 6:08pm Page 1136

Appendix A: Architecture Specifics


All of these functions are executed atomically, because lock statements are integrated in the assembler
code. There are also non-atomic versions of these functions, which are prefixed with a double underscore
(for example,__set_bit).

A.8.2 Conversion between Byte Orders


Architectures supported by the kernel use one of two byte orders — little endian or big endian.
Some architectures are able to handle both, but one must be configured. The kernel must there-
fore provide functions to convert data between both orders. For device drivers, it is particularly
important that function versions are available to convert a specific byte order to the format used by
the host without the need for numerous#ifdefpre-processor statements. The kernel provides the
<byteorder/little_endian.h>and<byteorder/big_endian.h>files. The version for the current
processor is linked into<asm-arch/byteorder.h>.^2

In order to implement the functions for converting between byte orders, the kernel needs efficient
ways of swapping bytes that can be optimized for each specific processor. C default functions are
defined in<byteoorder/swab.h>, but they can be overwritten by a processor-specific implementation.
__arch__swab16,__arch__swab32,and__arch__swab64swap the bytes between the representations,
and therefore convert big endian to little endian and vice versa.__swab16p,__arch__swab32p,and
__arch__swab64pdo the same for pointer variables.swabstands forswapbytes.

The__arch__operationpre-processor constant (__arch__swab16p, for example) must be set if an archi-
tecture provides an optimized version of one of these functions.

The following functions implement the conversion routines for little endian hosts as follows (note that
the conversion routines perform a null operation if they are executed on a number already in the relevant
format):

<byteorder/little_endian.h>
#define __constant_htonl(x) ((__force __be32)___constant_swab32((x)))
#define __constant_ntohl(x) ___constant_swab32((__force __be32)(x))
#define __constant_htons(x) ((__force __be16)___constant_swab16((x)))
#define __constant_ntohs(x) ___constant_swab16((__force __be16)(x))
#define __constant_cpu_to_le64(x) ((__force __le64)(__u64)(x))
#define __constant_le64_to_cpu(x) ((__force __u64)(__le64)(x))
#define __constant_cpu_to_le32(x) ((__force __le32)(__u32)(x))
#define __constant_le32_to_cpu(x) ((__force __u32)(__le32)(x))
#define __constant_cpu_to_le16(x) ((__force __le16)(__u16)(x))
#define __constant_le16_to_cpu(x) ((__force __u16)(__le16)(x))
#define __constant_cpu_to_be64(x) ((__force __be64)___constant_swab64((x)))
#define __constant_be64_to_cpu(x) ___constant_swab64((__force __u64)(__be64)(x))
#define __constant_cpu_to_be32(x) ((__force __be32)___constant_swab32((x)))
#define __constant_be32_to_cpu(x) ___constant_swab32((__force __u32)(__be32)(x))
#define __constant_cpu_to_be16(x) ((__force __be16)___constant_swab16((x)))
#define __constant_be16_to_cpu(x) ___constant_swab16((__force __u16)(__be16)(x))
#define __cpu_to_le64(x) ((__force __le64)(__u64)(x))
#define __le64_to_cpu(x) ((__force __u64)(__le64)(x))
#define __cpu_to_le32(x) ((__force __le32)(__u32)(x))

(^2) The byte order for VAX systems used to be declared as 3412 in<byteorder/pdp_endian.h>. However, because the architec-
ture is not supported by the kernel, this was somewhat pointless, so the file was removed during the development of kernel 2.6.21.

Free download pdf