-
Notifications
You must be signed in to change notification settings - Fork 59
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
Changes from all commits
1c47247
0f813a5
70ee5b7
f7f5c6d
ae04b87
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
fn main() { | ||
println!("cargo:rerun-if-changed=target.json"); | ||
println!("cargo:rerun-if-changed=layout.ld"); | ||
} | ||
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,2 @@ | ||
global_asm!(include_str!("note.s")); | ||
global_asm!(include_str!("ram32.s")); | ||
global_asm!(include_str!("ram64.s")); | ||
global_asm!(include_str!("gdt64.s")); |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
use core::mem::size_of; | ||
|
||
bitflags::bitflags! { | ||
// An extension of x86_64::structures::gdt::DescriptorFlags | ||
struct Descriptor: u64 { | ||
const LIMIT_0_15 = 0xFFFF; | ||
const BASE_0_23 = 0xFF_FFFF << 16; | ||
const ACCESSED = 1 << 40; | ||
const WRITABLE = 1 << 41; // Only for Data-Segments | ||
const READABLE = 1 << 41; // Only for Code-Segments | ||
const EXPANSION = 1 << 42; // Only for Data-Segments | ||
const CONFORMING = 1 << 42; // Only for Code-Segments | ||
const EXECUTABLE = 1 << 43; | ||
const USER_SEGMENT = 1 << 44; | ||
const DPL_RING_3 = 3 << 45; | ||
const PRESENT = 1 << 47; | ||
const LIMIT_16_19 = 0xF << 48; | ||
const SOFTWARE = 1 << 52; | ||
const BIT64 = 1 << 53; | ||
const BIT32 = 1 << 54; | ||
const GRANULARITY = 1 << 55; | ||
const BASE_24_31 = 0xFF << 56; | ||
|
||
// All segments are nonconforming, non-system, ring-0 only, and present. | ||
// We set ACCESSED in advance to avoid writing to the descriptor. | ||
const COMMON = Self::ACCESSED.bits | Self::USER_SEGMENT.bits | Self::PRESENT.bits; | ||
// BIT32 must be 0, all other bits (not yet mentioned) are ignored. | ||
const CODE64 = Self::COMMON.bits | Self::EXECUTABLE.bits | Self::BIT64.bits; | ||
} | ||
} | ||
|
||
// An alternative to x86_64::structures::DescriptorTablePointer that avoids | ||
// "pointer-to-integer cast" (which rust does not support in statics). | ||
#[repr(C, packed)] | ||
struct Pointer { | ||
limit: u16, | ||
base: &'static Descriptor, | ||
} | ||
|
||
impl Pointer { | ||
const fn new(gdt: &'static [Descriptor]) -> Self { | ||
let size = gdt.len() * size_of::<Descriptor>(); | ||
Self { | ||
limit: size as u16 - 1, | ||
base: &gdt[0], | ||
} | ||
} | ||
} | ||
|
||
// Our 64-bit GDT lives in RAM, so it can be accessed like any other global. | ||
#[no_mangle] | ||
static GDT64_PTR: Pointer = Pointer::new(&GDT64); | ||
static GDT64: [Descriptor; 2] = [Descriptor::empty(), Descriptor::CODE64]; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -38,6 +38,7 @@ mod boot; | |
mod bzimage; | ||
mod efi; | ||
mod fat; | ||
mod gdt; | ||
mod loader; | ||
mod mem; | ||
mod paging; | ||
|
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, | ||
|
@@ -53,3 +55,37 @@ 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(); | ||
|
||
// We make sure our ELF Note has an alignment of 4 for maximum compatibility. | ||
// Some software (QEMU) calculates padding incorectly if alignment != 4. | ||
#[repr(C, packed(4))] | ||
struct Note { | ||
name_size: u32, | ||
desc_size: u32, | ||
kind: u32, | ||
name: Name, | ||
desc: Desc, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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... :-) There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 There type of 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. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I added a comment about alignment to |
||
} | ||
|
||
// 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, | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool!