【问题标题】:How can I create a PVH "kernel" that will be run by qemu如何创建将由 qemu 运行的 PVH“内核”
【发布时间】:2021-02-06 01:50:04
【问题描述】:

我想要一个简单的 PVH 内核,它将由 qemu 加载并启动入口点。到目前为止,我有我的链接器脚本:

ENTRY(pvh_start_addr)
SECTIONS
{
    . = 1M;
    .text : { *(.boot.text)
              *(.text) }
    . = ALIGN(4K);
    .data : { *(.data) }
    .bss : { *(.bss) }
    .notes : { *(.notes) }
}

和代码:

.section .notes, "a"
.balign 4096
.align 4
.long 4  
.long 4 
.long 18  /* XEN..PHYS32 */
.asciz "Xen"
.align 4
.long  pvh_start_addr
.long  0x101000
.align 4

.balign 16
.code64
.section            ".boot.text", "ax"

.global pvh_start_addr
pvh_start_addr:
    jmp pvh_start_addr

Qemu 通过获取错误的起始地址将精灵加载为 PVH 二进制文件。无论如何,它的 SEG 故障在这里:

qemu-5.1.0/hw/i386/x86.c:417
417     pvh_start_addr = *elf_note_data_addr;

这会起作用还是我需要其他精灵笔记才能起作用?

【问题讨论】:

    标签: qemu boot xen


    【解决方案1】:

    您创建 ELF 注释的代码似乎对注释描述符字段的大小有错误的值:n_namesz 和 n_descsz 字段都有“.long 4”,但尽管名称字段确实是 4 个字节长("Xen\0") 描述符在 64 位系统上是 8 字节长(因为它是 ".long pvh_start_addr")。

    您可以考虑在 ELFNOTE 宏上使用Xen itself uses 的一些变体:

     #define ELFNOTE(name, type, desc)                   \
         .pushsection .note.name                       ; \
         .align 4                                      ; \
         .long 2f - 1f         /* namesz */            ; \
         .long 4f - 3f         /* descsz */            ; \
         .long type            /* type   */            ; \
     1:.asciz #name            /* name   */            ; \
     2:.align 4                                        ; \
     3:desc                    /* desc   */            ; \
     4:.align 4                                        ; \
         .popsection
    

    然后允许您(假设您已经为常量 18 定义了常量 XEN_ELFNOTE_PHYS32_ENTRY)来编写

    ELFNOTE(Xen, XEN_ELFNOTE_PHYS32_ENTRY, .long my_entry_label)
    

    并让宏为您计算名称和描述符大小。

    【讨论】:

    • ELFNOTE 宏只消耗三个参数,为什么还要向宏传递四个参数?
    • 只是一个错字/thinko——“.long”后面不应该有逗号,因为整个“.long my_entry_label”是宏的第三个参数。我已经编辑了答案来解决这个问题。
    【解决方案2】:

    qemu 加载 ELF 文件时有一个 but 。对于 64 位 ELF 文件,对齐方式仍然是 32 位值。

    uint64_t phdr_align = *(uint64_t *)arg2;
    

    应该改成

    uint64_t phdr_align = *(uint32_t *)arg2;
    

    【讨论】:

    • 我不确定您建议的修复是否正确。我认为您建议更改的传递给 read_pvh_start_addr() 函数的参数 arg2 是指向 elf32_phdr 或 elf64_phdr 结构中的 p_align 字段的指针。对于 64 位 ELF 文件,elf64_phdr 将 p_align 定义为 Elf64_Xword,因此它是 64 位,并且将指针转换为 uint32_t* 会做错事。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-19
    • 2018-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多