From 580bb93803d16566ccb064ffc963eab04c5c83f5 Mon Sep 17 00:00:00 2001 From: Alejandro Jimenez Date: Mon, 3 Feb 2020 23:27:49 -0500 Subject: [PATCH] pvh: Introduce hvm_start_info structure Introduce the layout and define the start_info and memory map table entry structures used by the PVH boot protocol. The hvm_start_info structure is akin to the 'zeropage' in Linux boot protocol, specifying the small set of parameters required by the PVH protocol. Signed-off-by: Alejandro Jimenez --- src/loader/start_info.rs | 298 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 298 insertions(+) create mode 100644 src/loader/start_info.rs diff --git a/src/loader/start_info.rs b/src/loader/start_info.rs new file mode 100644 index 00000000..590def3e --- /dev/null +++ b/src/loader/start_info.rs @@ -0,0 +1,298 @@ +// Copyright © 2020, Oracle and/or its affiliates. +// +/* + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Copyright (c) 2016, Citrix Systems, Inc. + */ + +/* + * A canonical version of this file is provided by Xen's + * xen/include/public/arch-x86/hvm/start_info.h + * + * Start of day structure passed to PVH guests and to HVM guests in %ebx. + * + * NOTE: nothing will be loaded at physical address 0, so a 0 value in any + * of the address fields should be treated as not present. + * + * 0 +----------------+ + * | magic | Contains the magic value XEN_HVM_START_MAGIC_VALUE + * | | ("xEn3" with the 0x80 bit of the "E" set). + * 4 +----------------+ + * | version | Version of this structure. Current version is 1. New + * | | versions are guaranteed to be backwards-compatible. + * 8 +----------------+ + * | flags | SIF_xxx flags. + * 12 +----------------+ + * | nr_modules | Number of modules passed to the kernel. + * 16 +----------------+ + * | modlist_paddr | Physical address of an array of modules + * | | (layout of the structure below). + * 24 +----------------+ + * | cmdline_paddr | Physical address of the command line, + * | | a zero-terminated ASCII string. + * 32 +----------------+ + * | rsdp_paddr | Physical address of the RSDP ACPI data structure. + * 40 +----------------+ + * | memmap_paddr | Physical address of the (optional) memory map. Only + * | | present in version 1 and newer of the structure. + * 48 +----------------+ + * | memmap_entries | Number of entries in the memory map table. Zero + * | | if there is no memory map being provided. Only + * | | present in version 1 and newer of the structure. + * 52 +----------------+ + * | reserved | Version 1 and newer only. + * 56 +----------------+ + * + * The layout of each entry in the module structure is the following: + * + * 0 +----------------+ + * | paddr | Physical address of the module. + * 8 +----------------+ + * | size | Size of the module in bytes. + * 16 +----------------+ + * | cmdline_paddr | Physical address of the command line, + * | | a zero-terminated ASCII string. + * 24 +----------------+ + * | reserved | + * 32 +----------------+ + * + * The layout of each entry in the memory map table is as follows: + * + * 0 +----------------+ + * | addr | Base address + * 8 +----------------+ + * | size | Size of mapping in bytes + * 16 +----------------+ + * | type | Type of mapping as defined between the hypervisor + * | | and guest. + * 20 +----------------| + * | reserved | + * 24 +----------------+ + * + * The address and sizes are always a 64bit little endian unsigned integer. + */ + +// Rust definitions needed to enable PVH boot protocol +#[repr(C)] +#[derive(Debug, Copy, Clone, Default)] +pub struct hvm_start_info { + pub magic: u32, + pub version: u32, + pub flags: u32, + pub nr_modules: u32, + pub modlist_paddr: u64, + pub cmdline_paddr: u64, + pub rsdp_paddr: u64, + pub memmap_paddr: u64, + pub memmap_entries: u32, + pub reserved: u32, +} + +#[repr(C)] +#[derive(Debug, Copy, Clone, Default)] +pub struct hvm_memmap_table_entry { + pub addr: u64, + pub size: u64, + pub type_: u32, + pub reserved: u32, +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn bindgen_test_layout_hvm_start_info() { + assert_eq!( + ::std::mem::size_of::(), + 56usize, + concat!("Size of: ", stringify!(hvm_start_info)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(hvm_start_info)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).magic as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(hvm_start_info), + "::", + stringify!(magic) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).version as *const _ as usize }, + 4usize, + concat!( + "Offset of field: ", + stringify!(hvm_start_info), + "::", + stringify!(version) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).flags as *const _ as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(hvm_start_info), + "::", + stringify!(flags) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).nr_modules as *const _ as usize }, + 12usize, + concat!( + "Offset of field: ", + stringify!(hvm_start_info), + "::", + stringify!(nr_modules) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).modlist_paddr as *const _ as usize + }, + 16usize, + concat!( + "Offset of field: ", + stringify!(hvm_start_info), + "::", + stringify!(modlist_paddr) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).cmdline_paddr as *const _ as usize + }, + 24usize, + concat!( + "Offset of field: ", + stringify!(hvm_start_info), + "::", + stringify!(cmdline_paddr) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).rsdp_paddr as *const _ as usize }, + 32usize, + concat!( + "Offset of field: ", + stringify!(hvm_start_info), + "::", + stringify!(rsdp_paddr) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).memmap_paddr as *const _ as usize }, + 40usize, + concat!( + "Offset of field: ", + stringify!(hvm_start_info), + "::", + stringify!(memmap_paddr) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).memmap_entries as *const _ as usize + }, + 48usize, + concat!( + "Offset of field: ", + stringify!(hvm_start_info), + "::", + stringify!(memmap_entries) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).reserved as *const _ as usize }, + 52usize, + concat!( + "Offset of field: ", + stringify!(hvm_start_info), + "::", + stringify!(reserved) + ) + ); + } + + #[test] + fn bindgen_test_layout_hvm_memmap_table_entry() { + assert_eq!( + ::std::mem::size_of::(), + 24usize, + concat!("Size of: ", stringify!(hvm_memmap_table_entry)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(hvm_memmap_table_entry)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).addr as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(hvm_memmap_table_entry), + "::", + stringify!(addr) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).size as *const _ as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(hvm_memmap_table_entry), + "::", + stringify!(size) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).type_ as *const _ as usize + }, + 16usize, + concat!( + "Offset of field: ", + stringify!(hvm_memmap_table_entry), + "::", + stringify!(type_) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).reserved as *const _ as usize + }, + 20usize, + concat!( + "Offset of field: ", + stringify!(hvm_memmap_table_entry), + "::", + stringify!(reserved) + ) + ); + } +}