kernel crash 发生后的那些事(二)

__do_kernel_fault主要包含两个函数show_pte and die.
/**************************************************************************/
void show_pte(struct mm_struct *mm, unsigned long addr)
{
    pgd_t *pgd;

    if (!mm)
        mm = &init_mm;

    printk(KERN_ALERT "pgd = %p\n", mm->pgd);
    pgd = pgd_offset(mm, addr);
    printk(KERN_ALERT "[%08lx] *pgd=%08llx",
            addr, (long long)pgd_val(*pgd));

    do {
        pud_t *pud;
        pmd_t *pmd;
        pte_t *pte;

        if (pgd_none(*pgd)){
            printk(KERN_ALERT "pgd_none\n");
            break;
        }
    }while(0);
    printk("\n");
}
这里涉及页表目录和页表项的操作。
对arm体系结构而言,相关的宏包含在文件arch/arm/include/asm/pgtable.h中,如以下:
/* to find an entry in a page-table-directory */
#define pgd_index(addr)        ((addr) >> PGDIR_SHIFT)
#define pgd_offset(mm, addr)    ((mm)->pgd + pgd_index(addr))
#define pgd_val(x)    ((x).pgd[0])

在文件arch/arm/include/asm/pgtable.h中包含
#ifdef CONFIG_ARM_LPAE
#include <asm/pgtable-3level.h>
#else
#include <asm/pgtable-2level.h>
#endif
根据.config 文件,可知没有定义CONFIG_ARM_LPAE,固包含头文件
arch/arm/include/asm/pgtable-2level-types.h
arch/arm/include/asm/pgtable-2level.h
比如PGDIR_SHIFT在这些文件中定义。

从crash的分析结果中,可以明确看出 pgd_t,pud_t,pmd_t,pte_t的定义。
crash> whatis pgd_t
typedef unsigned int [2] pgd_t;
SIZE: 8

crash> whatis pud_t
typedef struct {
    pgd_t pgd;
} pud_t;
SIZE: 8

crash> whatis pmd_t
typedef unsigned int pmd_t;
SIZE: 4

crash> whatis pte_t
typedef unsigned int pte_t;
SIZE: 4

对该例而言,pgd = e6390000
crash> rd 0xe6390000 16
e6390000:  00000000 00000000 00000000 00000000

如打印显示的那样:
Unable to handle kernel NULL pointer dereference at virtual address 00000000
pgd = e6390000
[00000000] *pgd=00000000

这里应该弄清楚,arm中为什么pgd_t占8个字节?
task_struct/ mm_struct/ thread_info/ sp 等之间的关系。待续---

你可能感兴趣的:(kernel,Crash)