mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-10-01 11:05:46 +00:00
vmm: memory_manager: Expose the slots details via an I/O port
Expose the details of hotplug RAM slots via an I/O port. This will be consumed by the ACPI DSDT tables to report the hotplug memory details to the guest. Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
parent
9880a2aba9
commit
1218765df2
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
use arc_swap::ArcSwap;
|
use arc_swap::ArcSwap;
|
||||||
use arch::RegionType;
|
use arch::RegionType;
|
||||||
|
use devices::BusDevice;
|
||||||
use kvm_bindings::kvm_userspace_memory_region;
|
use kvm_bindings::kvm_userspace_memory_region;
|
||||||
use kvm_ioctls::*;
|
use kvm_ioctls::*;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
@ -27,6 +28,8 @@ struct HotPlugState {
|
|||||||
base: u64,
|
base: u64,
|
||||||
length: u64,
|
length: u64,
|
||||||
active: bool,
|
active: bool,
|
||||||
|
inserting: bool,
|
||||||
|
removing: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct MemoryManager {
|
pub struct MemoryManager {
|
||||||
@ -37,6 +40,7 @@ pub struct MemoryManager {
|
|||||||
fd: Arc<VmFd>,
|
fd: Arc<VmFd>,
|
||||||
mem_regions: Vec<Arc<GuestRegionMmap>>,
|
mem_regions: Vec<Arc<GuestRegionMmap>>,
|
||||||
hotplug_slots: Vec<HotPlugState>,
|
hotplug_slots: Vec<HotPlugState>,
|
||||||
|
selected_slot: usize,
|
||||||
backing_file: Option<PathBuf>,
|
backing_file: Option<PathBuf>,
|
||||||
mergeable: bool,
|
mergeable: bool,
|
||||||
allocator: Arc<Mutex<SystemAllocator>>,
|
allocator: Arc<Mutex<SystemAllocator>>,
|
||||||
@ -102,6 +106,86 @@ pub fn get_host_cpu_phys_bits() -> u8 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ENABLE_FLAG: usize = 0;
|
||||||
|
const INSERTING_FLAG: usize = 1;
|
||||||
|
const REMOVING_FLAG: usize = 2;
|
||||||
|
const EJECT_FLAG: usize = 3;
|
||||||
|
|
||||||
|
const BASE_OFFSET_LOW: u64 = 0;
|
||||||
|
const BASE_OFFSET_HIGH: u64 = 0x4;
|
||||||
|
const LENGTH_OFFSET_LOW: u64 = 0x8;
|
||||||
|
const LENGTH_OFFSET_HIGH: u64 = 0xA;
|
||||||
|
const STATUS_OFFSET: u64 = 0x14;
|
||||||
|
const SELECTION_OFFSET: u64 = 0;
|
||||||
|
|
||||||
|
impl BusDevice for MemoryManager {
|
||||||
|
fn read(&mut self, _base: u64, offset: u64, data: &mut [u8]) {
|
||||||
|
if self.selected_slot < self.hotplug_slots.len() {
|
||||||
|
let state = &self.hotplug_slots[self.selected_slot];
|
||||||
|
match offset {
|
||||||
|
BASE_OFFSET_LOW => {
|
||||||
|
data.copy_from_slice(&state.base.to_le_bytes()[..4]);
|
||||||
|
}
|
||||||
|
BASE_OFFSET_HIGH => {
|
||||||
|
data.copy_from_slice(&state.base.to_le_bytes()[4..]);
|
||||||
|
}
|
||||||
|
LENGTH_OFFSET_LOW => {
|
||||||
|
data.copy_from_slice(&state.length.to_le_bytes()[..4]);
|
||||||
|
}
|
||||||
|
LENGTH_OFFSET_HIGH => {
|
||||||
|
data.copy_from_slice(&state.length.to_le_bytes()[4..]);
|
||||||
|
}
|
||||||
|
STATUS_OFFSET => {
|
||||||
|
if state.active {
|
||||||
|
data[0] |= 1 << ENABLE_FLAG;
|
||||||
|
}
|
||||||
|
if state.inserting {
|
||||||
|
data[0] |= 1 << INSERTING_FLAG;
|
||||||
|
}
|
||||||
|
if state.removing {
|
||||||
|
data[0] |= 1 << REMOVING_FLAG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
warn!(
|
||||||
|
"Unexpected offset for accessing memory manager device: {:#}",
|
||||||
|
offset
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write(&mut self, _base: u64, offset: u64, data: &[u8]) {
|
||||||
|
match offset {
|
||||||
|
SELECTION_OFFSET => {
|
||||||
|
self.selected_slot = usize::from(data[0]);
|
||||||
|
}
|
||||||
|
STATUS_OFFSET => {
|
||||||
|
let state = &mut self.hotplug_slots[self.selected_slot];
|
||||||
|
// The ACPI code writes back a 1 to acknowledge the insertion
|
||||||
|
if (data[0] & (1 << INSERTING_FLAG) == 1 << INSERTING_FLAG) && state.inserting {
|
||||||
|
state.inserting = false;
|
||||||
|
}
|
||||||
|
// Ditto for removal
|
||||||
|
if (data[0] & (1 << REMOVING_FLAG) == 1 << REMOVING_FLAG) && state.removing {
|
||||||
|
state.removing = false;
|
||||||
|
}
|
||||||
|
// Trigger removal of "DIMM"
|
||||||
|
if data[0] & (1 << EJECT_FLAG) == 1 << EJECT_FLAG {
|
||||||
|
warn!("Ejection of memory not currently supported");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
warn!(
|
||||||
|
"Unexpected offset for accessing memory manager device: {:#}",
|
||||||
|
offset
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl MemoryManager {
|
impl MemoryManager {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
allocator: Arc<Mutex<SystemAllocator>>,
|
allocator: Arc<Mutex<SystemAllocator>>,
|
||||||
@ -157,6 +241,7 @@ impl MemoryManager {
|
|||||||
fd,
|
fd,
|
||||||
mem_regions,
|
mem_regions,
|
||||||
hotplug_slots,
|
hotplug_slots,
|
||||||
|
selected_slot: 0,
|
||||||
backing_file: backing_file.clone(),
|
backing_file: backing_file.clone(),
|
||||||
mergeable,
|
mergeable,
|
||||||
allocator: allocator.clone(),
|
allocator: allocator.clone(),
|
||||||
@ -274,6 +359,7 @@ impl MemoryManager {
|
|||||||
// Update the slot so that it can be queried via the I/O port
|
// Update the slot so that it can be queried via the I/O port
|
||||||
let mut slot = &mut self.hotplug_slots[self.next_hotplug_slot];
|
let mut slot = &mut self.hotplug_slots[self.next_hotplug_slot];
|
||||||
slot.active = true;
|
slot.active = true;
|
||||||
|
slot.inserting = true;
|
||||||
slot.base = region.start_addr().0;
|
slot.base = region.start_addr().0;
|
||||||
slot.length = region.len() as u64;
|
slot.length = region.len() as u64;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user