ARMV5 instruction set CPU (usually ARM9 architecture) does not support non -aligned access access by default, and CPUs of ARMV6 and above default support to process most non -aligned memory address access. Alignment means that the start address is an integer multiple of a word length, usually 4 bytes alignment.
By setting the content of/proc/cpu/alignment file content, the content of the non -aligned address in the kernel can be modified.
[email protected](none):~# cat /proc/cpu/alignment
User: 3905290
System: 0
Skipped: 0
Half: 0
Word: 0
DWord: 2672136
Multi: 1233154
User faults: 2 (fixup)
The last line of “User Faults” in this file means how to process non -aligned memory address access in the kernel. This value is a bitmap:
#define UM_WARN (1 << 0)
#define UM_FIXUP (1 << 1)
#define UM_SIGNAL (1 << 2)
UM_WARN: Only “Alignment Trap” warning.
UM_FIXUP: Try to properly handle non -alignment memory address.
UM_SIGNAL: When an uniform address access occurs, send the SIGBUS signal notification to the corresponding process.
Several processing methods can be combined, such as (um_warn | um_fixup), which is to give warning information while FIXUP. If set to 0, it is IGNORE.
For the CPU of ARMV5, the value of User Faults is 0, that is, ignoring an uniform address access. At this time, if the process accesses an uniform address, it will cause the program execution abnormality. If there is no uniform address access in the program, you can set it to FIXUP:
If you like
echo 2 > /proc/cpu/alignment
, the kernel will do additional work so that the access to the non -aligned memory address can get the correct result.
For the CPU of ARMV6 and above, the CPU itself requires supporting the processing of non -aligned address access, so basically do not need to care about the value set in/proc/cpu/alignment For non -alignment address access, software assistance is still required. Among these CPUs,/ProC/CPU/Alignment default to 2 (FIXUP).
For details, please refer to the kernel code arch/arm/mm/alignment.c: alignment_init (), hook_fault_code (), do_alignment ().
On a chip that does not support non -inside -in -memory access, you must pay attention to the conversion of compulsory types. For example, the following example:
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
void sigbus_handler(int sno)
{
printf(“signal %d captured\n”, sno);
exit(1);
}
int main(int argc, char *argv[])
{
char intarray[8] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88};
signal(SIGBUS, sigbus_handler);
printf(“int1 = 0x%08x, int2 = 0x%08x, int3 = 0x%08x, int4 = 0x%08x\n”,
*((int *)(intarray + 1)), *((int *)(intarray + 2)), *((int *)(intarray + 3)), *((int *)(intarray + 4)));
return 0;
}
The result of supporting non -alignment access systems is as follows (small end system):
[email protected]:~# ./testalign
int1 = 0x55443322, int2 = 0x66554433, int3 = 0x77665544, int4 = 0x88776655
and on the non -alignment access system, setting different values for/proc/cpu/alignment is also different:
~ # echo 0 > /proc/cpu/alignment
~ # ./testalign
int1 = 0x11443322, int2 = 0x22114433, int3 = 0x33221144, int4 = 0x88776655
~ #
~ # echo 2 > /proc/cpu/alignment
~ # ./testalign
int1 = 0x55443322, int2 = 0x66554433, int3 = 0x77665544, int4 = 0x88776655
~ #
~ # echo 1 > /proc/cpu/alignment
~ # ./testalign
Alignment trap: testalign (979) PC=0x0000860c Instr=0xe5931000 Address=0xbef6fc99 FSR 0x001
Alignment trap: testalign (979) PC=0x0000860c Instr=0xe5931000 Address=0xbef6fc99 FSR 0x001
int1 = 0x11443322, int2 = 0x22114433, int3 = 0x33221144, int4 = 0x88776655
~ #
~ # echo 4 > /proc/cpu/alignment
~ # ./testalign
signal 7 captured
~ #
Of course, it can also be set to 3, and give warnings while correctly processing non -aligned address access.
We can use the CHAR type to read and write non -aligned memory to avoid non -aligned address processing, or use functions such as MEMCPY to avoid problems caused by assignment or forced type conversion.
Look at the following example:
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h> /* memcpy */
struct pack_info {
unsigned char sno;
unsigned int len;
} __attribute__((packed));
void sigbus_handler(int sno)
{
printf(“signal %d captured\n”, sno);
exit(1);
}
int main(int argc, char *argv[])
{
signal(SIGBUS, sigbus_handler);
struct pack_info * mem_cos = (struct pack_info *)malloc(sizeof(struct pack_info));
if (!mem_cos)
return 1;
unsigned int * cy_len = &mem_cos->len;
mem_cos->sno = 0x12;
mem_cos->len = 0x55667788;
/ * 1. Assign value to member variables * /
mem_cos->len = 0xaabbccdd;
/ * 2. The value of the pointer CY_LEN is assigned * /
*cy_len = 0xaabbccdd;
/ * 3. Assign to MEMCPY * /
unsigned int cy_len_i = 0xaabbccdd;
memcpy(cy_len, &cy_len_i, 4);
printf(“sno = %#x, len = %#x\n”, mem_cos->sno, mem_cos->len);
free(mem_cos);
return 0;
}
Since the __attribute __ ((Packed)) attribute is added to the struct pack_info, its Len member’s address is not 4 -byte alignment.
The code above uses three ways to assign a value to Len members. In the second way, there will be problems with the second way without supporting non -alignment access systems, and the expected results cannot be obtained.
———————
Original: https://blog.csdn.net/jasonChen_GBD/Details/51535018