From 67d7b3827213bd39420631ee72e3289ea5ed0cdc Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Fri, 19 Jan 2024 13:20:43 +0100 Subject: [PATCH] SVSM/requests: Move request processing into separate kernel task Move all request processing out of the idle task into a separate kernel task. Signed-off-by: Joerg Roedel --- src/cpu/smp.rs | 6 +++-- src/requests.rs | 66 +++++++++++++++++++++++++++++++++++++++---------- src/svsm.rs | 7 ++++-- 3 files changed, 62 insertions(+), 17 deletions(-) diff --git a/src/cpu/smp.rs b/src/cpu/smp.rs index 5fd4db8553..17054e0d74 100644 --- a/src/cpu/smp.rs +++ b/src/cpu/smp.rs @@ -9,8 +9,8 @@ extern crate alloc; use crate::acpi::tables::ACPICPUInfo; use crate::cpu::percpu::{this_cpu, this_cpu_mut, PerCpu}; use crate::cpu::vmsa::init_svsm_vmsa; -use crate::requests::request_loop; -use crate::task::schedule_init; +use crate::requests::{request_loop, request_processing_main}; +use crate::task::{create_kernel_task, schedule_init, TASK_FLAG_SHARE_PT}; fn start_cpu(apic_id: u32) { unsafe { @@ -76,6 +76,8 @@ fn start_ap() { #[no_mangle] pub extern "C" fn ap_request_loop() { + create_kernel_task(request_processing_main, TASK_FLAG_SHARE_PT) + .expect("Failed to launch request processing task"); request_loop(); panic!("Returned from request_loop!"); } diff --git a/src/requests.rs b/src/requests.rs index 6771a48a99..ad30b3e120 100644 --- a/src/requests.rs +++ b/src/requests.rs @@ -50,25 +50,23 @@ fn request_loop_once( return Ok(false); } - let caa_addr = this_cpu().caa_addr().ok_or_else(|| { - log::error!("No CAA mapped - bailing out"); - SvsmReqError::FatalError(SvsmError::MissingCAA) - })?; - - let guest_pending = GuestPtr::::new(caa_addr); - let pending = guest_pending.read()?; - guest_pending.write(0)?; - - if pending != 1 { - return Ok(false); - } - match protocol { 0 => core_protocol_request(request, params).map(|_| true), _ => Err(SvsmReqError::unsupported_protocol()), } } +fn check_requests() -> Result { + if let Some(caa_addr) = this_cpu().caa_addr() { + let guest_pending = GuestPtr::::new(caa_addr); + let p = guest_pending.read()?; + guest_pending.write(0)?; + Ok(p == 1) + } else { + Ok(false) + } +} + pub fn request_loop() { loop { // Determine whether the guest is runnable. If not, halt and wait for @@ -104,6 +102,46 @@ pub fn request_loop() { // Clear EFER.SVME in guest VMSA vmsa.disable(); + let rax = vmsa.rax; + let protocol = (rax >> 32) as u32; + let request = (rax & 0xffff_ffff) as u32; + + match check_requests() { + Ok(pending) => { + if pending { + this_cpu_mut().process_requests(); + } + } + Err(SvsmReqError::RequestError(code)) => { + log::debug!( + "Soft error handling protocol {} request {}: {:?}", + protocol, + request, + code + ); + } + Err(SvsmReqError::FatalError(err)) => { + log::error!( + "Fatal error handling core protocol request {}: {:?}", + request, + err + ); + break; + } + } + } +} + +#[no_mangle] +pub extern "C" fn request_processing_main() { + let apic_id = this_cpu().get_apic_id(); + + log::info!("Launching request-processing task on CPU {}", apic_id); + + loop { + this_cpu_mut().wait_for_requests(); + + let vmsa = this_cpu_mut().guest_vmsa(); let rax = vmsa.rax; let protocol = (rax >> 32) as u32; let request = (rax & 0xffff_ffff) as u32; @@ -136,4 +174,6 @@ pub fn request_loop() { // Write back results params.write_back(vmsa); } + + panic!("Request processing task died unexpectedly"); } diff --git a/src/svsm.rs b/src/svsm.rs index 0da432e541..6eed29afc5 100755 --- a/src/svsm.rs +++ b/src/svsm.rs @@ -41,14 +41,14 @@ use svsm::mm::memory::init_memory_map; use svsm::mm::pagetable::paging_init; use svsm::mm::virtualrange::virt_log_usage; use svsm::mm::{init_kernel_mapping_info, PerCPUPageMappingGuard}; -use svsm::requests::{request_loop, update_mappings}; +use svsm::requests::{request_loop, request_processing_main, update_mappings}; use svsm::serial::SerialPort; use svsm::sev::secrets_page::{copy_secrets_page, disable_vmpck0, SecretsPage}; use svsm::sev::utils::{rmp_adjust, RMPFlags}; use svsm::sev::{init_hypervisor_ghcb_features, sev_status_init}; use svsm::svsm_console::SVSMIOPort; use svsm::svsm_paging::{init_page_table, invalidate_early_boot_memory}; -use svsm::task::schedule_init; +use svsm::task::{create_kernel_task, schedule_init, TASK_FLAG_SHARE_PT}; use svsm::types::{PageSize, GUEST_VMPL, PAGE_SIZE}; use svsm::utils::{halt, immut_after_init::ImmutAfterInitCell, zero_mem_region}; @@ -453,6 +453,9 @@ pub extern "C" fn svsm_main() { } } + create_kernel_task(request_processing_main, TASK_FLAG_SHARE_PT) + .expect("Failed to launch request processing task"); + #[cfg(test)] crate::test_main();