Handavei @ Jilin Normal University
2014.12.10
Reprint please indicate the source
*****************************************************
About the kernel error "Unable to handle kernel paging request at virtual address" is mostly due to the use of the program is not available pointers, the way to locate such problems is very simple, and I hope that my description is simple enough Use.
Take one of my examples below to illustrate:
Epc:exception program counter, exception counter, Ra:return address return addresses
We can be based on "CPU 0 unable to handle kernel paging request at virtual address 0000000000000078, EPC = = Ffffffff805e96e8, RA = = f Fffffff80ec73d0 "Find the specific location of the EPC, and then according to the specific assembler to locate the specific cause of the EPC, in addition, if you have to know all the call path. Then the method of locating the EPC repeatedly, according to the call trace to gradually locate.
when you compile Linux, you generate a System.map , vmlinux, and VMLINUX.O
We can use System.map and VMLINUX.O. Because Vmlinux may have been compressed by a particular compression tool (depending on your makefile), you cannot disassemble it using the Objdump tool.
Open System.map First:
The EPC = = Ffffffff805e96e8 in the Ffffffff805e96e8 address copy down, directly in the System.map inside the search, if not found, then ffffffff805e96e8 the last two bits deleted, that is FFFFFFFF80 5e96, find this address, most of the situation can be found, my following:
It seems that the problem is in the Add_mtd_device function.
The location of the EPC is at Ffffffff805e96e8, Add_mtd_device's address is in ffffffff805e96c0, so it should be in Add_mtd_device. ffffffff805e96e8-ffffffff805e96c0 = 0x28 There is a problem with this offset position.
Now we need to observe the assembly code of VMLINUX.O, find the assembly of the Add_mtd_device function, and observe the assembly language of the 0x28 position.
First use Xxx-objdump (XXX for the specific cross-compiler tool prefix) to disassemble the VMLINUX.O, my practice is:
MIPS64-OCTEON-LINUX-GNU-OBJDUMP-DR VMLINUX.O >> LINUX-DR
After opening linux-dr This file, find the definition of Add_mtd_device:
You can see that the assembly of the 0x28 location:
28:dc820078 LD v0,120 (A0)
The meaning of LD V0 (A0) is:
The address of the value of the register A0 is first taken, and then the value at 120 bytes after that address is loaded into the V0 register .
(A0) is the address of the A0 register, and A0 is the Register that is responsible for the first parameter of the transfer function.
DC 8 2 0078 is the LD V0, (a0) corresponding machine code.
Based on CPU 0 unable to handle kernel paging request at virtual address 0000000000000078 This is a hint to know that
is in An error occurred while 0x78 (120) Address of A0 was evaluated , it is likely that the A0 address itself is not available. If you can confirm it, you can prove that the first parameter of Add_mtd_device uses an unavailable pointer.
This time you can check the source code, I believe you have the ability to quickly locate the problem.
But if the function is large and not easy to locate, then we can use the information of 120 to locate the specific statement in the function.
My example:
Open the Linux kernel source code, calculate the position of the 120 bytes in the first parameter type of Add_mtd_device (), and get the parameter member:
Vi-t Add_mtd_device
Such as:
Find the type of the first parameter, struct mtd_info definition, by progressively calculating each member offset (note padding bytes),
The member of the 120th byte can be calculated as Backing_dev_info. In the code, then, the EPC program is the first place where the member appears.
If this offset is too large and difficult to calculate, you might want to customize a variable of that parameter type before calling the function in the code.
Estimate a approximate member, calculate their offsets, and then calculate the 120 member position based on knowing the offset of the member. would be easier.
My approach is to:
struct Mtd_info my = {0};
unsigned long len = (unsigned long) & (My.backing_dev_info)-(unsigned long) &my;
PRINTK ("sizeof is = 0x%lu\n", Len);
Of course, this requires rebooting the device and load the newly compiled Linux.
For positioning the EPC position, summarize:
1, open System.map, find the address of the nearest function before the EPC. Calculates the offset value of the EPC distance to the function.
2, use Objdump to find the function, analyze the assembly code at the EPC offset.
3, open the source code, according to the analysis of the information obtained from the Assembly code to locate.
I hope the above information is helpful to you.
Locating Linux kernel Panic location according to EPC