tdger
tdger

Reputation: 9

How can I create a PVH "kernel" that will be run by qemu

I want a simple PVH kernel that will be loaded by qemu and the entry point started. Thus far I have my linker script:

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

and the code:

.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 loads the elf as a PVH binary by gets the start address wrong. Anyhow, it SEG faults here:

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

Will this work or do I need other elf notes for this to work?

Upvotes: 1

Views: 2461

Answers (2)

Peter Maydell
Peter Maydell

Reputation: 11383

Your code to create the ELF note seems to have the wrong value for the size of the note descriptor field: you have ".long 4" for both the n_namesz and n_descsz fields, but although the name field is indeed 4 bytes long ("Xen\0") the descriptor is 8 bytes long on a 64-bit system (because it is the ".long pvh_start_addr").

You might consider using some variant on the ELFNOTE macro that 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

which then allows you (assuming you've defined a constant XEN_ELFNOTE_PHYS32_ENTRY for the constant 18) to write

ELFNOTE(Xen, XEN_ELFNOTE_PHYS32_ENTRY, .long my_entry_label)

and let the macro do the work of calculating the name and descriptor sizes for you.

Upvotes: 2

tdger
tdger

Reputation: 9

There is a but in qemu when it loads the ELF file. For a 64bit ELF file the alignment is still a 32 bit value.

uint64_t phdr_align = *(uint64_t *)arg2;

should probably be changed to

uint64_t phdr_align = *(uint32_t *)arg2;

Upvotes: -1

Related Questions