如何创建将由qemu运行的PVH“内核”

问题描述

我想要一个简单的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;

这项工作还是需要其他精灵注释才能完成?

解决方法

您用于创建ELF注释的代码似乎对注释描述符字段的大小具有错误的值:n_namesz和n_descsz字段都具有“ .long 4”,但是尽管name字段的确是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)

,然后让宏为您计算名称和描述符大小。

,

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

uint64_t phdr_align = *(uint64_t *)arg2;

应该更改为

uint64_t phdr_align = *(uint32_t *)arg2;