Recently in doing the kernel from the small-end processor (arm) to the big-endian processor (PPC) of the work, now kernel into the console stable work, the basic work has been completed, but the transplant has a lot of experience or need to summarize, Today, the kernel is summed up for processing the byte-order of the size-end.
Before writing the size-end byte sequence thinking, the article link address: http://blog.csdn.NET/skyflying2012/article/details/42065427.
According to the previous understanding, the byte sequence can be considered as the processor subjective concept, just like how people look at things, the processor is big and small end, for memory reading and writing, as long as the data type consistent, there is no byte-order problem.
So I feel that the biggest difference between byte order is the reading and writing of registers. Because the peripheral registers are small ends (based on the kernel code, the following are explained in detail)
According to my previous byte-sequence thinking, there are 2 different scenarios for register reading and writing:
(1) To solve this problem from the hardware, for 32-bit CPU, the 32 data bus is back, but this may be problematic for addressing less than 32 bits of data, and not all modules are back (such as memory), which also involves compiler problems.
(2) from the software to solve this problem, in the underlying read and write register functions, the read/write data to swap.
As a software personnel, I am most concerned about the feasibility of the second option, because of the data in the reading and writing registers to swap, increasing the complexity of the register read and write, the original storage/loading instructions can be completed work, now may need to add some more swap-related instructions, can not guarantee the atomic nature of the register operation. For high-performance, large concurrent systems can cause competition.
Therefore, with the fewest instructions to complete the data swap and r/w registers, in order to ensure the normal stability of Linux system operation.
In the transplant bootloader I am the data to carry on the displacement to complete the swap, because bootloader single process, does not have the race state question.
This was a concern during the kernel migration, but found that kernel has provided a common function in the case of a large and small-end processor operation Register, which is Readl/writel (for example, to operate a 32-bit register).
For driver developers do not need to care about the processor's byte sequence, register operation directly using Readl/writel.
There are many articles on the web that refer to Readl/writel, but do not specifically analyze its implementation.
Today, we mainly analyze how to achieve efficient data swap and register reading and writing in Readl/writel. We take READL as an example, for the Big-endian processor, how to deal with the register data.
Kernel under READL defined below, in include/asm-generic/io.h
[plain] view plain copy #define READL (addr) __le32_to_cpu (__raw_readl (addr)) __RAW_READL is the lowest register read-write function, very simply, from Get the register data directly. To see the implementation of the __LE32_TO_CPU, this function has a different implementation for the byte order, for the small-end processor, in./include/linux/byteorder/little_endian.h, as follows:
[plain] view plain copy #define __LE32_TO_CPU (x) (__force __u32) (__LE32) (x)) is equivalent to doing nothing. For big-endian processors, in./include/linux/byteorder/big_endian.h, the following:
[plain] view plain copy #define __LE32_TO_CPU (x) __swab32 (__force __u32) (__LE32) (x)) the literal meaning can also be seen, __swab32 realize The data is flipped. Wait, we'll analyze the implementation of __SWAB32, the essence of this function.
But before this first consider a problem, for different CPUs, such as Arm MIPS PPC, how to choose to use Little_endian.h or big_endian.h it.
The answer is, for different processor platforms, there are arch/xxx/include/asm/byteorder.h header files, look at arm MIPS PPC Byteorder.h respectively.
Arch/arm/include/asm/byteorder.h
[Plain] View Plain copy * arch/arm/include/asm/byteorder.h * * arm endian-ness. in little endian mode, the data bus is connected such * that byte accesses appear as: * 0 = d0...d7, 1 = d8...d15, 2 = d16...d23, 3 = d24...d31 * and word accesses (data or instruction) appear as: * d0...d31 * * when in big endian mode, byte accesses appear as: * 0 = d24...d31, 1 = d16...d23, 2 = d8...d15, 3 = d0...d7 * and word accesses (data or instruction) appear as: * d0...d31 */ #ifndef __asm_ arm_byteorder_h #define __ASM_ARM_BYTEORDER_H #ifdef __armeb__ #include <linux/byteorder/big_endian.h> #else #include < linux/byteorder/little_endian.h> #endif #endif
Arch/mips/include/asm/byteorder.h
[plain] view plain copy