Skip to content

Move Note and GDT definitions into Rust #37

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Apr 15, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/asm/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
global_asm!(include_str!("note.s"));
global_asm!(include_str!("ram32.s"));
global_asm!(include_str!("ram64.s"));
global_asm!(include_str!("gdt64.s"));
20 changes: 0 additions & 20 deletions src/asm/note.s

This file was deleted.

34 changes: 34 additions & 0 deletions src/pvh.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use core::mem::size_of;

use crate::{
boot::{E820Entry, Info},
common,
Expand Down Expand Up @@ -53,3 +55,35 @@ impl Info for StartInfo {
}
}
}

// The PVH Boot Protocol starts at the 32-bit entrypoint to our firmware.
extern "C" {
fn ram32_start();
}

// The kind/name/desc of the PHV ELF Note are from xen/include/public/elfnote.h.
// This is the "Physical entry point into the kernel".
const XEN_ELFNOTE_PHYS32_ENTRY: u32 = 18;
type Name = [u8; 4];
type Desc = unsafe extern "C" fn();

#[repr(C, packed(4))]
struct Note {
name_size: u32,
desc_size: u32,
kind: u32,
name: Name,
desc: Desc,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interestingly when it was 4 bytes that forced a change in the Cloud Hypervisor PVH code to support it. It's ambiguous to me what it should be. But if it works... :-)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The size of Desc seems to depend on how the code in question is compiled. Linux sets a field of type _ASM_PTR, which is 8 bytes (at least on my kernel). The PVH Specification seems to indicate the type should be .long aka 4 bytes. I think it's fine for hypervisors to just support any size <= 8 for this field. QEMU just does a raw read of a size_t without checking descsz.

There type of namesz, descsz, and kind seems to usually be u32 (even for 64-bit ELF). That's what Linux does, NetBSD does, and what Oracle says to do. However, the gABI says they should be u64s but that seems to get ignored. See this mailing list discussion for more info.

The final complexity is alignment of the structure (and hence the containing phdr's alignment). Some loaders expect this to always be 4, others allow for other alignments but compute the structure padding incorrectly:

Using an alignment of 4 prevents any issues (as there will just not be any padding). This is what Linux does.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a comment about alignment to pvh.rs.

}

// This is: ELFNOTE(Xen, XEN_ELFNOTE_PHYS32_ENTRY, .quad ram32_start)
#[cfg(not(test))]
#[link_section = ".note"]
#[used]
static PVH_NOTE: Note = Note {
name_size: size_of::<Name>() as u32,
desc_size: size_of::<Desc>() as u32,
kind: XEN_ELFNOTE_PHYS32_ENTRY,
name: *b"Xen\0",
desc: ram32_start,
};