Reputation: 9
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
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
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