Skip to content

Commit 89538bc

Browse files
committed
api: implement API for getting guest memory mappings
Implement API /memory/mappings which returns the memory mappings of guest physical to host virtual memory. Signed-off-by: Babis Chalios <babis.chalios@e2b.dev>
1 parent 933e630 commit 89538bc

7 files changed

Lines changed: 70 additions & 2 deletions

File tree

src/firecracker/src/api_server/parsed_request.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ use super::request::vsock::parse_put_vsock;
3131
use crate::api_server::request::hotplug::memory::{
3232
parse_get_memory_hotplug, parse_patch_memory_hotplug, parse_put_memory_hotplug,
3333
};
34+
use crate::api_server::request::memory_info::parse_get_guest_memory_mappings;
3435
use crate::api_server::request::serial::parse_put_serial;
3536

3637
#[derive(Debug)]
@@ -91,6 +92,9 @@ impl TryFrom<&Request> for ParsedRequest {
9192
(Method::Get, "hotplug", None) if path_tokens.next() == Some("memory") => {
9293
parse_get_memory_hotplug()
9394
}
95+
(Method::Get, "memory", None) if path_tokens.next() == Some("mappings") => {
96+
parse_get_guest_memory_mappings()
97+
}
9498
(Method::Get, _, Some(_)) => method_to_error(Method::Get),
9599
(Method::Put, "actions", Some(body)) => parse_put_actions(body),
96100
(Method::Put, "balloon", Some(body)) => parse_put_balloon(body),
@@ -196,6 +200,7 @@ impl ParsedRequest {
196200
&serde_json::json!({ "firecracker_version": version.as_str() }),
197201
),
198202
VmmData::FullVmConfig(config) => Self::success_response_with_data(config),
203+
VmmData::MemoryMappings(mappings) => Self::success_response_with_data(mappings),
199204
},
200205
Err(vmm_action_error) => {
201206
let mut response = match vmm_action_error {
@@ -610,6 +615,9 @@ pub mod tests {
610615
&serde_json::json!({ "firecracker_version": version.as_str() }).to_string(),
611616
200,
612617
),
618+
VmmData::MemoryMappings(mappings) => {
619+
http_response(&serde_json::to_string(mappings).unwrap(), 200)
620+
}
613621
};
614622
let response = ParsedRequest::convert_to_response(&data);
615623
response.write_all(&mut buf).unwrap();
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
use vmm::rpc_interface::VmmAction;
2+
3+
use crate::api_server::parsed_request::{ParsedRequest, RequestError};
4+
5+
pub(crate) fn parse_get_guest_memory_mappings() -> Result<ParsedRequest, RequestError> {
6+
// TODO: Define the metric and then use it here
7+
// METRICS.get_api_requests.guest_memory_mappings_count.inc();
8+
Ok(ParsedRequest::new_sync(VmmAction::GetMemoryMappings))
9+
}

src/firecracker/src/api_server/request/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ pub mod hotplug;
1111
pub mod instance_info;
1212
pub mod logger;
1313
pub mod machine_configuration;
14+
pub mod memory_info;
1415
pub mod metrics;
1516
pub mod mmds;
1617
pub mod net;

src/vmm/src/lib.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,9 @@ use crate::devices::virtio::block::device::Block;
144144
use crate::devices::virtio::mem::{VIRTIO_MEM_DEV_ID, VirtioMem, VirtioMemError, VirtioMemStatus};
145145
use crate::devices::virtio::net::Net;
146146
use crate::logger::{METRICS, MetricsError, error, info, warn};
147-
use crate::persist::{MicrovmState, MicrovmStateError, VmInfo};
147+
use crate::persist::{GuestRegionUffdMapping, MicrovmState, MicrovmStateError, VmInfo};
148148
use crate::rate_limiter::BucketUpdate;
149+
use crate::utils::usize_to_u64;
149150
use crate::vmm_config::instance_info::{InstanceInfo, VmState};
150151
use crate::vstate::memory::{GuestMemory, GuestMemoryMmap, GuestMemoryRegion};
151152
use crate::vstate::vcpu::VcpuState;
@@ -690,6 +691,27 @@ impl Vmm {
690691
pub fn vm(&self) -> &Vm {
691692
&self.vm
692693
}
694+
695+
/// Get the list of mappings for guest memory
696+
pub fn guest_memory_mappings(&self, page_size: usize) -> Vec<GuestRegionUffdMapping> {
697+
let mut mappings = vec![];
698+
let mut offset = 0;
699+
700+
for region in self.vm.guest_memory().iter() {
701+
#[allow(deprecated)]
702+
mappings.push(GuestRegionUffdMapping {
703+
base_host_virt_addr: region.as_ptr() as u64,
704+
size: region.size(),
705+
offset,
706+
page_size,
707+
page_size_kib: page_size,
708+
});
709+
710+
offset += usize_to_u64(region.size());
711+
}
712+
713+
mappings
714+
}
693715
}
694716

695717
/// Process the content of the MPIDR_EL1 register in order to be able to pass it to KVM

src/vmm/src/rpc_interface.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ use crate::vmm_config::drive::{BlockDeviceConfig, BlockDeviceUpdateConfig, Drive
3030
use crate::vmm_config::entropy::{EntropyDeviceConfig, EntropyDeviceError};
3131
use crate::vmm_config::instance_info::InstanceInfo;
3232
use crate::vmm_config::machine_config::{MachineConfig, MachineConfigError, MachineConfigUpdate};
33+
use crate::vmm_config::meminfo::MemoryMapingsResponse;
3334
use crate::vmm_config::memory_hotplug::{
3435
MemoryHotplugConfig, MemoryHotplugConfigError, MemoryHotplugSizeUpdate,
3536
};
@@ -146,6 +147,8 @@ pub enum VmmAction {
146147
/// Update the microVM configuration (memory & vcpu) using `VmUpdateConfig` as input. This
147148
/// action can only be called before the microVM has booted.
148149
UpdateMachineConfiguration(MachineConfigUpdate),
150+
/// Get the guest memory mappings to host memory
151+
GetMemoryMappings,
149152
}
150153

151154
/// Wrapper for all errors associated with VMM actions.
@@ -228,6 +231,8 @@ pub enum VmmData {
228231
VirtioMemStatus(VirtioMemStatus),
229232
/// The status of the virtio-balloon hinting run
230233
HintingStatus(HintingStatus),
234+
/// The guest memory mapping information.
235+
MemoryMappings(MemoryMapingsResponse),
231236
}
232237

233238
/// Trait used for deduplicating the MMDS request handling across the two ApiControllers.
@@ -495,7 +500,8 @@ impl<'a> PrebootApiController<'a> {
495500
| UpdateNetworkInterface(_)
496501
| StartFreePageHinting(_)
497502
| GetFreePageHintingStatus
498-
| StopFreePageHinting => Err(VmmActionError::OperationNotSupportedPreBoot),
503+
| StopFreePageHinting
504+
| GetMemoryMappings => Err(VmmActionError::OperationNotSupportedPreBoot),
499505
#[cfg(target_arch = "x86_64")]
500506
SendCtrlAltDel => Err(VmmActionError::OperationNotSupportedPreBoot),
501507
}
@@ -771,6 +777,7 @@ impl RuntimeApiController {
771777
.update_memory_hotplug_size(cfg.requested_size_mib)
772778
.map(|_| VmmData::Empty)
773779
.map_err(VmmActionError::MemoryHotplugUpdate),
780+
GetMemoryMappings => self.get_guest_memory_mappings(),
774781
// Operations not allowed post-boot.
775782
ConfigureBootSource(_)
776783
| ConfigureLogger(_)
@@ -937,6 +944,14 @@ impl RuntimeApiController {
937944
.map_err(NetworkInterfaceError::DeviceUpdate)
938945
.map_err(VmmActionError::NetworkConfig)
939946
}
947+
948+
/// Get guest memory mappings
949+
fn get_guest_memory_mappings(&self) -> Result<VmmData, VmmActionError> {
950+
let vmm = self.vmm.lock().expect("Poisoned lock");
951+
let page_size = self.vm_resources.machine_config.huge_pages.page_size();
952+
let mappings = vmm.guest_memory_mappings(page_size);
953+
Ok(VmmData::MemoryMappings(MemoryMapingsResponse { mappings }))
954+
}
940955
}
941956

942957
#[cfg(test)]

src/vmm/src/vmm_config/meminfo.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
use serde::Serialize;
2+
3+
use crate::persist::GuestRegionUffdMapping;
4+
5+
/// Serializeable struct that contains information about guest's memory mappings
6+
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize)]
7+
pub struct MemoryMapingsResponse {
8+
/// Vector with mappings from guest physical to host virtual memoryv
9+
pub mappings: Vec<GuestRegionUffdMapping>,
10+
}
11+

src/vmm/src/vmm_config/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ pub mod entropy;
2020
pub mod instance_info;
2121
/// Wrapper for configuring the memory and CPU of the microVM.
2222
pub mod machine_config;
23+
/// Wrapper for getting memory-related information.
24+
pub mod meminfo;
2325
/// Wrapper for configuring memory hotplug.
2426
pub mod memory_hotplug;
2527
/// Wrapper for configuring the metrics.

0 commit comments

Comments
 (0)