Xen中Dom0启动linux_kernel中引发Xen panic的异常问题

现象描述:

        在MTK平台移植Xen,利用Xen构建的dom0启动linux_kernel从而启动android,在调试过程中需要在linux_kernel的汇编阶段增加打印log确认dom0中的kernel是否启动,在增加log的打印过程,引发了Xen中的panic问题,即说找不到guest os。

        

 

    在进入linux_kernel头文件head.s中b   primary_entry和efi_signature_nop(这是汇编的一个宏也是一条指令)之间增加如图所示的打印会造成上面Xen panic的问题,而在b   primary_entry之后增加打印并不会引起Xen中panic的问题。

 现象原因分析:

为了分析问题需要将内核编译生成的vmlinux反汇编对比一下指令码。

        反汇编命令:

aarch64-linux-gnu-objdump -S vmlinux > vmlinux.S

        反汇编结果:

        

        依据panic的日志不停增加log找到Xen中发生panic的源码所在之处,定位发生panic的原因

        发生panic的日志:

       正常运行的日志:

        

        对比日志所定位到xen解析kernel的函数实现中

static int __init kernel_zimage64_probe(struct kernel_info *info,
                                        paddr_t addr, paddr_t size)
{
    /* linux/Documentation/arm64/booting.txt */
#pragma pack(1)
    struct {
        uint32_t magic0;
        uint32_t res0;
        //uint64_t res7;
        //uint32_t res8;
        uint64_t text_offset;  /* Image load offset */
        uint64_t res1;
        uint64_t res2;
        /* zImage V1 only from here */
        uint64_t res3;
        uint64_t res4;
        uint64_t res5;
        uint64_t res7;
        uint32_t res8;
        uint32_t magic1;
        uint32_t res6;
    } zimage;
#pragma pack()
    uint64_t start, end;

    if ( size < sizeof(zimage) )
        return -EINVAL;

    copy_from_paddr(&zimage, addr, sizeof(zimage));
    printk("0x%x 0x%x\n",zimage.magic0,zimage.magic1);

    if ( zimage.magic0 != ZIMAGE64_MAGIC_V0 &&
         zimage.magic1 != ZIMAGE64_MAGIC_V1 )
        return -EINVAL;

    /* Currently there is no length in the header, so just use the size */
    start = 0;
    end = size;

    /*
     * Given the above this check is a bit pointless, but leave it
     * here in case someone adds a length field in the future.
     */
    if ( (end - start) > size )
        return -EINVAL;

    info->zimage.kernel_addr = addr;
    printk("zimage.kernel_addr: 0x%lx\n",info->zimage.kernel_addr);
    info->zimage.len = end - start;
    info->zimage.text_offset = zimage.text_offset;

    info->load = kernel_zimage_load;

    info->type = DOMAIN_64BIT;

    return 0;
}

         结合前面反汇编的结果和打印的信息的log,可以发现正常运行zimage.magic0应该是0xfa405a4d,而zimage.magic1应该等于0x644d5241,可以明显看出panic发的日志中zimage.magic1却是等于0。通个分析反汇编的结果可以算出正常zimage.magic1是相对ffffffc008000000偏移了56个字节,而增加log之后,zimage.magic1需要偏移68个字节才能得到0x644d5241。

 

 

        

        因为后面copy_from_paddr(&zimage, addr, sizeof(zimage));会从内核所在地址拷贝数据到zimage的结果里面来,所以关注这里的zimage结构体,其中res7和res8是我自己添加的,经过前面的分析要想将 zimage.magic1的变成0x644d5241,需要在原来的基础上偏移12个字节,也就是8+4个字节就行,在magic1前+12字节,重新编译刷机,发现遇到新的问题,Xen无法将dom0的kernel拷贝到dom0的物理内存中(相对虚拟机是物理的,相对Xen_hypervisor就是虚拟的)

 

        正常拷贝到00000000c000000: 

        拷贝失败: 

 根据这个kernel_zimage_place(info),可以看到00000000c000000这个加载值是由下面这个计算出来,等于说正常运行时的text_offset偏移量应该为0,而发生panic的原因是因为偏移位置被改变了,此时text_offset为0x390001f05807ffcf,接下来调整结构体zimage中text_offset,使其偏移之后值为0就行。

        修改的同时注意取消掉结构体内存对齐的问题,在原先的基础上偏移res7和res8(12个字节)就行。

         

        注意:通过Xen构建的dom0启动kernel,在通过设备树传递kernel的大小必须是解压之后的大小,至少传递的kernel大小需要大于解压之后,后续Xen需要依据这个kernel大小建议对等页表。就这块内存映射到真实的设备物理地址上去。(在之前的调试中由于我传递的kernel的大小是为未解压的内核大小-20M左右,但从反汇编的结果a9d0000看出来这个是远远大于压缩内核的大小的)。

 

panic解决之后的现象:

        这个时候看到swapper就可以确认dom0启动kernel是成功了

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值