-
Notifications
You must be signed in to change notification settings - Fork 40
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
SSE and FPU support #410
base: main
Are you sure you want to change the base?
SSE and FPU support #410
Conversation
Some cpuid functions require a non-zero value of xcr0 to be passed. Signed-off-by: Vasant Karasulli <vkarasulli@suse.de>
Check for the available SSE/FPU related features and initialize them. Signed-off-by: Vasant Karasulli <vkarasulli@suse.de>
Reserve xsave area for tasks and kernel to manage xstate. Signed-off-by: Vasant Karasulli <vkarasulli@suse.de>
use xsaveopt/xrstor instructions to save and restore task context. Signed-off-by: Vasant Karasulli <vkarasulli@suse.de>
These in-svsm tests check if tasks can use some sse/fpu instructions and xstate is saved/restored properly during task switches. Signed-off-by: Vasant Karasulli <vkarasulli@suse.de>
cr4_osfxsr_enable(); | ||
cr0_sse_enable(); | ||
} else { | ||
log::info!("Legacy SSE instructions not supported by this hardware"); |
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.
Perhaps this should be an error?
log::info!("Legacy SSE instructions not supported by this hardware"); | |
log::error!("Legacy SSE instructions not supported by this hardware"); |
fn xcr0_set() { | ||
let mut xsse_val: u32; | ||
let ecx_val = 0; | ||
let mut edx_val: u32; | ||
|
||
unsafe { | ||
asm!("xgetbv", out("eax") xsse_val, in("ecx") ecx_val, out("edx") edx_val, | ||
options(att_syntax)) | ||
} | ||
|
||
// set bits [0-2] in XCR0 to enable extended SSE | ||
xsse_val |= 0x7; | ||
unsafe { | ||
asm!("xsetbv", in("eax") xsse_val, in("ecx") ecx_val, in("edx") edx_val, | ||
options(att_syntax)) | ||
} | ||
} |
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.
Rust has builtins for extended control register access, so these should work:
fn xcr0_set() { | |
let mut xsse_val: u32; | |
let ecx_val = 0; | |
let mut edx_val: u32; | |
unsafe { | |
asm!("xgetbv", out("eax") xsse_val, in("ecx") ecx_val, out("edx") edx_val, | |
options(att_syntax)) | |
} | |
// set bits [0-2] in XCR0 to enable extended SSE | |
xsse_val |= 0x7; | |
unsafe { | |
asm!("xsetbv", in("eax") xsse_val, in("ecx") ecx_val, in("edx") edx_val, | |
options(att_syntax)) | |
} | |
} | |
use core::arch::x86_64::{_xgetbv, _xsetbv}; | |
fn xcr0_set() { | |
unsafe { | |
// set bits [0-2] in XCR0 to enable extended SSE | |
let xr0 = _xgetbv(0) | 0x7; | |
_xsetbv(0, xr0); | |
} | |
} |
#[repr(C)] | ||
pub struct Task { | ||
pub rsp: u64, | ||
|
||
/// XSave area address for the task | ||
pub xsa_addr: u64, |
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.
pub xsa_addr: u64, | |
pub xsa_addr: VirtAddr, |
|
||
impl XSaveArea { | ||
pub fn new() -> Result<Self, SvsmError> { | ||
let pg = allocate_file_page_ref()?; |
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.
Any reason we're not using a regular page, i.e. allocate_page()
?
xcr0_set(); | ||
check_xsave_features(); | ||
} else { | ||
log::info!("XSAVE is not supported by this hardware"); |
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.
Same here, perhaps this should be an error. Also, can we continue operation without XSAVE?
This PR entails following changes:
I will submit the related exception handling in another PR.