-
Notifications
You must be signed in to change notification settings - Fork 121
Fixes to simplify VTL1 boot sequence #652
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
Open
tgopinath-microsoft
wants to merge
3
commits into
main
Choose a base branch
from
user/thara/simplify-vtl1-boot
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,200 +1,49 @@ | ||
| // Copyright (c) Microsoft Corporation. | ||
| // Licensed under the MIT license. | ||
|
|
||
| //! VTL1 kernel boot parameters (compatible with Linux kernel's boot_params structure and command line) | ||
|
|
||
| use crate::mshv::vtl1_mem_layout::{ | ||
| VTL1_BOOT_PARAMS_PAGE, VTL1_CMDLINE_PAGE, VtlMemoryError, get_address_of_special_page, | ||
| }; | ||
| use core::ffi::{CStr, c_char}; | ||
| use num_enum::TryFromPrimitive; | ||
| use litebox_common_linux::errno::Errno; | ||
| use spin::Once; | ||
|
|
||
| #[cfg(debug_assertions)] | ||
| use crate::debug_serial_println; | ||
|
|
||
| // This module defines a simplified Linux boot params structure | ||
| // (based on arch/x86/include/uapi/asm/bootparam.h and | ||
| // arch/x86/include/uapi/asm/e820.h). We need this because VTL0 kernel | ||
| // passes memory information to VTL1 kernel via boot params. | ||
|
|
||
| const E820_MAX_ENTRIES: usize = 128; | ||
|
|
||
| const E820_RAM: u32 = 1; | ||
| const E820_RESERVED: u32 = 2; | ||
| const E820_ACPI: u32 = 3; | ||
| const E820_NVS: u32 = 4; | ||
| const E820_UNUSABLE: u32 = 5; | ||
| const E820_PMEM: u32 = 7; | ||
| const E820_PRAM: u32 = 12; | ||
| const E820_RESERVED_KERN: u32 = 128; | ||
|
|
||
| static POSSIBLE_CPUS: Once<u32> = Once::new(); | ||
| static VTL1_MEMORY_INFO: Once<(u64, u64)> = Once::new(); | ||
|
|
||
| #[derive(Default, Clone, Copy)] | ||
| #[repr(C, packed)] | ||
| struct BootE820Entry { | ||
| pub addr: u64, | ||
| pub size: u64, | ||
| pub typ: u32, | ||
| } | ||
|
|
||
| #[derive(Clone, Copy)] | ||
| #[repr(C, packed)] | ||
| struct BootParams { | ||
| _unused0: [u8; 720], // fields in this area are not used. | ||
| e820_table: [BootE820Entry; E820_MAX_ENTRIES], | ||
| _unused1: [u8; 816], // fields in this area are not used. | ||
| } | ||
|
|
||
| impl BootParams { | ||
| pub fn new() -> Self { | ||
| Self { | ||
| _unused0: [0; 720], | ||
| e820_table: [BootE820Entry::default(); E820_MAX_ENTRIES], | ||
| _unused1: [0; 816], | ||
| } | ||
| } | ||
|
|
||
| #[cfg(debug_assertions)] | ||
| pub fn dump(&self) { | ||
| for entry in self.e820_table { | ||
| let typ_val = entry.typ; | ||
|
|
||
| if E820Type::try_from(typ_val).unwrap_or(E820Type::Unknown) == E820Type::Unknown { | ||
| break; | ||
| } else { | ||
| let addr_val = entry.addr; | ||
| let size_val = entry.size; | ||
| debug_serial_println!( | ||
| "addr: {:#x}, size: {:#x}, type: {:?}", | ||
| addr_val, | ||
| size_val, | ||
| typ_val | ||
| ); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| pub fn memory_info(&self) -> Result<(u64, u64), VtlMemoryError> { | ||
| for entry in self.e820_table { | ||
| let typ_val = entry.typ; | ||
|
|
||
| match E820Type::try_from(typ_val).unwrap_or(E820Type::Unknown) { | ||
| E820Type::Ram => { | ||
| let addr_val = entry.addr; | ||
| let size_val = entry.size; | ||
| return Ok((addr_val, size_val)); | ||
| } | ||
| E820Type::Unknown => { | ||
| return Err(VtlMemoryError::InvalidBootParams); | ||
| } | ||
| _ => {} | ||
| } | ||
| } | ||
|
|
||
| Err(VtlMemoryError::InvalidBootParams) | ||
| } | ||
| } | ||
|
|
||
| impl Default for BootParams { | ||
| fn default() -> Self { | ||
| Self::new() | ||
| } | ||
| } | ||
|
|
||
| #[cfg(debug_assertions)] | ||
| fn dump_boot_params() { | ||
| let boot_params = get_address_of_special_page(VTL1_BOOT_PARAMS_PAGE) as *const BootParams; | ||
| unsafe { | ||
| (*boot_params).dump(); | ||
| } | ||
| } | ||
|
|
||
| #[cfg(debug_assertions)] | ||
| fn dump_cmdline() { | ||
| let cmdline = get_address_of_special_page(VTL1_CMDLINE_PAGE) as *const c_char; | ||
| if cmdline.is_null() { | ||
| return; | ||
| } | ||
|
|
||
| if let Some(cmdline_str) = unsafe { CStr::from_ptr(cmdline).to_str().ok() } { | ||
| crate::debug_serial_println!("{}", cmdline_str); | ||
| } | ||
| } | ||
|
|
||
| /// Funtion to get the guest physical start address and size of VTL1 memory | ||
| pub fn get_vtl1_memory_info() -> Result<(u64, u64), VtlMemoryError> { | ||
| pub fn get_vtl1_memory_info() -> Result<(u64, u64), Errno> { | ||
| if let Some(pair) = VTL1_MEMORY_INFO.get().copied() { | ||
| Ok(pair) | ||
| } else { | ||
| Err(VtlMemoryError::InvalidBootParams) | ||
| Err(Errno::EINVAL) | ||
| } | ||
| } | ||
|
|
||
| /// Funtion to get the number of possible cpus from the command line (Linux kernel's num_possible_cpus()) | ||
| pub fn get_num_possible_cpus() -> Result<u32, VtlMemoryError> { | ||
| pub fn get_num_possible_cpus() -> Result<u32, Errno> { | ||
| if let Some(cpus) = POSSIBLE_CPUS.get() { | ||
| Ok(*cpus) | ||
| } else { | ||
| Err(VtlMemoryError::InvalidCmdLine) | ||
| Err(Errno::EINVAL) | ||
| } | ||
| } | ||
|
|
||
| fn save_vtl1_memory_info() -> Result<(), VtlMemoryError> { | ||
| let boot_params = get_address_of_special_page(VTL1_BOOT_PARAMS_PAGE) as *const BootParams; | ||
| if let Some((start, size)) = unsafe { (*boot_params).memory_info().ok() } { | ||
| fn save_vtl1_memory_info(start: u64, size: u64) -> Result<(), Errno> { | ||
| if start > 0 && size > 0 { | ||
| VTL1_MEMORY_INFO.call_once(|| (start, size)); | ||
| return Ok(()); | ||
| } | ||
| Err(VtlMemoryError::InvalidBootParams) | ||
| Err(Errno::EINVAL) | ||
| } | ||
|
|
||
| fn save_possible_cpus() -> Result<(), VtlMemoryError> { | ||
| let cmdline = get_address_of_special_page(VTL1_CMDLINE_PAGE) as *const c_char; | ||
| if cmdline.is_null() { | ||
| return Err(VtlMemoryError::InvalidCmdLine); | ||
| } | ||
|
|
||
| if let Some(cmdline_str) = unsafe { CStr::from_ptr(cmdline).to_str().ok() } { | ||
| for token in cmdline_str.split_whitespace() { | ||
| if token.starts_with("possible_cpus=") | ||
| && let Some((_, v)) = token.split_once('=') | ||
| { | ||
| let num = v.parse::<u32>().unwrap_or(0); | ||
| if num > 0 { | ||
| POSSIBLE_CPUS.call_once(|| num); | ||
| return Ok(()); | ||
| } | ||
| } | ||
| } | ||
| fn save_possible_cpus(possible_cpus: u32) -> Result<(), Errno> { | ||
| if possible_cpus > 0 { | ||
| POSSIBLE_CPUS.call_once(|| possible_cpus); | ||
| return Ok(()); | ||
| } | ||
| Err(VtlMemoryError::InvalidCmdLine) | ||
| Err(Errno::EINVAL) | ||
| } | ||
| /// # Panics | ||
| /// | ||
| /// Panics if possible cpus or vtl1 memory extraction fails | ||
| pub fn parse_boot_info() { | ||
| #[cfg(debug_assertions)] | ||
| dump_cmdline(); | ||
| #[cfg(debug_assertions)] | ||
| dump_boot_params(); | ||
| save_possible_cpus().unwrap(); // Panic if CPU extraction fails | ||
| save_vtl1_memory_info().unwrap(); // Panic if memory extraction fails | ||
| } | ||
|
|
||
| /// E820 entry type | ||
| #[derive(Debug, PartialEq, TryFromPrimitive)] | ||
| #[repr(u32)] | ||
| enum E820Type { | ||
| Ram = E820_RAM, | ||
| Reserved = E820_RESERVED, | ||
| Acpi = E820_ACPI, | ||
| Nvs = E820_NVS, | ||
| Unusable = E820_UNUSABLE, | ||
| Pmem = E820_PMEM, | ||
| Pram = E820_PRAM, | ||
| ReservedKern = E820_RESERVED_KERN, | ||
| Unknown = 0xffff_ffff, | ||
| pub fn save_boot_info(possible_cpus: u32, mem_pa: u64, mem_size: u64) { | ||
| save_possible_cpus(possible_cpus).unwrap(); // Panic if CPU extraction fails | ||
| save_vtl1_memory_info(mem_pa, mem_size).unwrap(); // Panic if memory extraction fails | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Seems that no one is using this function anymore.
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.
yes you are right. Would mind though if we keep this a little while longer ,please ? I want to do the multi instance support for TA and dynamic TA loading and if we still do not need it, we can remove it