Find the physical address of exception vector table from kernel module

The exception vector table has remained fairly constant in Linux, from 2.6.35 to the most recent mainline. It is allocated very early in the boot phase and involves the memblock boot allocator. The files involved are entry-armv.S, traps.c, and vmlinux.lds.S (the linker script) in the kernel directory with init.c and mmu.c in the mm (or memory management ARM directory). Also, the vector table must be mapped all the time and it is readable by a user process. This is used by the kernel user helpers; the helper routines are also mapped to this page.

An explaination

From vmlinux.lds.S,

The vectors and stubs are relocatable code, and the only thing that matters is their relative offsets

__vectors_start represents the code in the vector page and is found in entry-armv.S. However, the function is relocated in traps.c. The boot allocator reserves a page for the virtual 0xffff000 address (if high vectors are configured). In your 2.6.35 kernel, the memblock allocator is used in init.c. Here mmu.c’s devicemaps_init() allocates a page by calling early_alloc(). This page doesn’t follow the normal kernel address space rules and virt_to_phys may not be used as the virtual address is forced.

However, a kernel address does exist with the original memblock_alloc() return address. This is the pointer vector in devicemaps_init(); this address does work with virt_to_phys and phys_to_virt.

The physical address of __vectors_start, etc in entry-armv.S can be easily found and a physical address calculated; however, it is discarded at the end of the init phase and I think you aren’t interested in this.

An answer

You can call, memblock_dump_all(void) and look at dmesg and use these pointers to try and locate the vector page. It will be 4k size. You could alter the devicemaps_init() to export the vector value. The only way with an unmodified kernel is to do a walk of the ARM mmu tables; that is another story.

Leave a Comment