From f40dd4a9932049f05a3ac1279d6d0a60c38c2e9b Mon Sep 17 00:00:00 2001 From: Yi Wang Date: Sun, 26 Nov 2023 18:59:54 +0800 Subject: [PATCH] vmm: add endpoint api for NMI support Add http endpoint for trigger nmi. Signed-off-by: Yi Wang --- fuzz/fuzz_targets/http_api.rs | 4 ++++ vmm/src/api/http/http_endpoint.rs | 3 ++- vmm/src/api/http/mod.rs | 4 +++- vmm/src/api/mod.rs | 40 +++++++++++++++++++++++++++++++ vmm/src/lib.rs | 9 +++++++ 5 files changed, 58 insertions(+), 2 deletions(-) diff --git a/fuzz/fuzz_targets/http_api.rs b/fuzz/fuzz_targets/http_api.rs index 1f3c92c47..24e7c0fe3 100644 --- a/fuzz/fuzz_targets/http_api.rs +++ b/fuzz/fuzz_targets/http_api.rs @@ -273,6 +273,10 @@ impl RequestHandler for StubApiRequestHandler { fn vm_send_migration(&mut self, _: VmSendMigrationData) -> Result<(), MigratableError> { Ok(()) } + + fn vm_nmi(&mut self) -> Result<(), VmError> { + Ok(()) + } } fn http_receiver_stub(exit_evt: EventFd, api_evt: EventFd, api_receiver: Receiver) { diff --git a/vmm/src/api/http/http_endpoint.rs b/vmm/src/api/http/http_endpoint.rs index 141cc1d0f..81825685e 100644 --- a/vmm/src/api/http/http_endpoint.rs +++ b/vmm/src/api/http/http_endpoint.rs @@ -9,7 +9,7 @@ use crate::api::http::{error_response, EndpointHandler, HttpError}; use crate::api::VmCoredump; use crate::api::{ AddDisk, ApiAction, ApiRequest, VmAddDevice, VmAddFs, VmAddNet, VmAddPmem, VmAddUserDevice, - VmAddVdpa, VmAddVsock, VmBoot, VmConfig, VmCounters, VmDelete, VmPause, VmPowerButton, + VmAddVdpa, VmAddVsock, VmBoot, VmConfig, VmCounters, VmDelete, VmNmi, VmPause, VmPowerButton, VmReboot, VmReceiveMigration, VmRemoveDevice, VmResize, VmResizeZone, VmRestore, VmResume, VmSendMigration, VmShutdown, VmSnapshot, }; @@ -172,6 +172,7 @@ vm_action_put_handler!(VmReboot); vm_action_put_handler!(VmPause); vm_action_put_handler!(VmResume); vm_action_put_handler!(VmPowerButton); +vm_action_put_handler!(VmNmi); vm_action_put_handler_body!(VmAddDevice); vm_action_put_handler_body!(AddDisk); diff --git a/vmm/src/api/http/mod.rs b/vmm/src/api/http/mod.rs index a34df8a17..dee4118c4 100644 --- a/vmm/src/api/http/mod.rs +++ b/vmm/src/api/http/mod.rs @@ -8,7 +8,7 @@ use self::http_endpoint::{VmActionHandler, VmCreate, VmInfo, VmmPing, VmmShutdow use crate::api::VmCoredump; use crate::api::{ AddDisk, ApiError, ApiRequest, VmAddDevice, VmAddFs, VmAddNet, VmAddPmem, VmAddUserDevice, - VmAddVdpa, VmAddVsock, VmBoot, VmCounters, VmDelete, VmPause, VmPowerButton, VmReboot, + VmAddVdpa, VmAddVsock, VmBoot, VmCounters, VmDelete, VmNmi, VmPause, VmPowerButton, VmReboot, VmReceiveMigration, VmRemoveDevice, VmResize, VmResizeZone, VmRestore, VmResume, VmSendMigration, VmShutdown, VmSnapshot, }; @@ -268,6 +268,8 @@ pub static HTTP_ROUTES: Lazy = Lazy::new(|| { .insert(endpoint!("/vmm.ping"), Box::new(VmmPing {})); r.routes .insert(endpoint!("/vmm.shutdown"), Box::new(VmmShutdown {})); + r.routes + .insert(endpoint!("/vm.nmi"), Box::new(VmActionHandler::new(&VmNmi))); r }); diff --git a/vmm/src/api/mod.rs b/vmm/src/api/mod.rs index ad74aa9e5..de68e23e2 100644 --- a/vmm/src/api/mod.rs +++ b/vmm/src/api/mod.rs @@ -159,6 +159,9 @@ pub enum ApiError { /// Error triggering power button VmPowerButton(VmError), + + /// Error triggering NMI + VmNmi(VmError), } pub type ApiResult = Result; @@ -200,6 +203,7 @@ impl Display for ApiError { VmReceiveMigration(migratable_error) => write!(f, "{}", migratable_error), VmSendMigration(migratable_error) => write!(f, "{}", migratable_error), VmPowerButton(vm_error) => write!(f, "{}", vm_error), + VmNmi(vm_error) => write!(f, "{}", vm_error), } } } @@ -353,6 +357,8 @@ pub trait RequestHandler { &mut self, send_data_migration: VmSendMigrationData, ) -> Result<(), MigratableError>; + + fn vm_nmi(&mut self) -> Result<(), VmError>; } /// It would be nice if we could pass around an object like this: @@ -380,6 +386,7 @@ fn get_response( let (response_sender, response_receiver) = channel(); let request = action.request(data, response_sender); + // Send the VM request. api_sender.send(request).map_err(ApiError::RequestSend)?; api_evt.write(1).map_err(ApiError::EventFdWrite)?; @@ -1415,3 +1422,36 @@ impl ApiAction for VmmShutdown { Ok(()) } } + +pub struct VmNmi; + +impl ApiAction for VmNmi { + type RequestBody = (); + type ResponseBody = Option; + + fn request(&self, _: Self::RequestBody, response_sender: Sender) -> ApiRequest { + Box::new(move |vmm| { + info!("API request event: VmNmi"); + + let response = vmm + .vm_nmi() + .map_err(ApiError::VmNmi) + .map(|_| ApiResponsePayload::Empty); + + response_sender + .send(response) + .map_err(VmmError::ApiResponseSend)?; + + Ok(false) + }) + } + + fn send( + &self, + api_evt: EventFd, + api_sender: Sender, + data: Self::RequestBody, + ) -> ApiResult { + get_response_body(self, api_evt, api_sender, data) + } +} diff --git a/vmm/src/lib.rs b/vmm/src/lib.rs index d55c346ef..3cc4560a6 100644 --- a/vmm/src/lib.rs +++ b/vmm/src/lib.rs @@ -1840,6 +1840,15 @@ impl RequestHandler for Vmm { } } + fn vm_nmi(&mut self) -> result::Result<(), VmError> { + if let Some(ref mut vm) = self.vm { + info!("nmi"); + vm.power_button() + } else { + Err(VmError::VmNotRunning) + } + } + fn vm_receive_migration( &mut self, receive_data_migration: VmReceiveMigrationData,