Added a class which owns GuestRam and manages runtime memory allocations
This commit is contained in:
parent
ffefbd9283
commit
90e1b26a11
@ -4,7 +4,7 @@ use std::thread;
|
|||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
|
|
||||||
use crate::virtio::{VirtioDeviceOps,VirtioBus,VirtQueue};
|
use crate::virtio::{VirtioDeviceOps,VirtioBus,VirtQueue};
|
||||||
use crate::memory::GuestRam;
|
use crate::memory::MemoryManager;
|
||||||
use crate::vm::Result;
|
use crate::vm::Result;
|
||||||
|
|
||||||
|
|
||||||
@ -25,7 +25,7 @@ impl VirtioRandom {
|
|||||||
|
|
||||||
impl VirtioDeviceOps for VirtioRandom {
|
impl VirtioDeviceOps for VirtioRandom {
|
||||||
|
|
||||||
fn start(&mut self, _memory: GuestRam, mut queues: Vec<VirtQueue>) {
|
fn start(&mut self, _memory: &MemoryManager, mut queues: Vec<VirtQueue>) {
|
||||||
thread::spawn(move|| {
|
thread::spawn(move|| {
|
||||||
run(queues.pop().unwrap())
|
run(queues.pop().unwrap())
|
||||||
});
|
});
|
||||||
|
@ -4,7 +4,7 @@ use std::thread::spawn;
|
|||||||
use termios::*;
|
use termios::*;
|
||||||
|
|
||||||
use crate::virtio::{VirtioDeviceOps,VirtioBus, VirtQueue};
|
use crate::virtio::{VirtioDeviceOps,VirtioBus, VirtQueue};
|
||||||
use crate::memory::GuestRam;
|
use crate::memory::MemoryManager;
|
||||||
use crate::vm::Result;
|
use crate::vm::Result;
|
||||||
|
|
||||||
const VIRTIO_ID_CONSOLE: u16 = 3;
|
const VIRTIO_ID_CONSOLE: u16 = 3;
|
||||||
@ -40,7 +40,7 @@ impl VirtioSerial {
|
|||||||
.register()
|
.register()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start_console(&self, _memory: GuestRam, q: VirtQueue) {
|
fn start_console(&self, _memory: &MemoryManager, q: VirtQueue) {
|
||||||
spawn(move || {
|
spawn(move || {
|
||||||
loop {
|
loop {
|
||||||
q.wait_ready().unwrap();
|
q.wait_ready().unwrap();
|
||||||
@ -81,7 +81,7 @@ impl VirtioDeviceOps for VirtioSerial {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn start(&mut self, memory: GuestRam, mut queues: Vec<VirtQueue>) {
|
fn start(&mut self, memory: &MemoryManager, mut queues: Vec<VirtQueue>) {
|
||||||
let mut term = Terminal::create(queues.remove(0));
|
let mut term = Terminal::create(queues.remove(0));
|
||||||
self.start_console(memory, queues.remove(0));
|
self.start_console(memory, queues.remove(0));
|
||||||
|
|
||||||
@ -208,6 +208,8 @@ impl Terminal {
|
|||||||
} else {
|
} else {
|
||||||
abort_cnt += 1;
|
abort_cnt += 1;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
println!("n = {}", n);
|
||||||
}
|
}
|
||||||
|
|
||||||
if abort_cnt == 3 {
|
if abort_cnt == 3 {
|
||||||
|
116
rust/src/memory/manager.rs
Normal file
116
rust/src/memory/manager.rs
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
use std::os::unix::io::RawFd;
|
||||||
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
|
use crate::memory::{GuestRam, SystemAllocator, Mapping, Error, Result};
|
||||||
|
use crate::kvm::Kvm;
|
||||||
|
use crate::system::BitVec;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct MemoryManager {
|
||||||
|
kvm: Kvm,
|
||||||
|
ram: GuestRam,
|
||||||
|
device_memory: Arc<RwLock<DeviceMemory>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MemoryManager {
|
||||||
|
|
||||||
|
pub fn new(kvm: Kvm, ram: GuestRam, allocator: SystemAllocator) -> Self {
|
||||||
|
let device_memory = RwLock::new(DeviceMemory::new(ram.region_count(), allocator)).into();
|
||||||
|
MemoryManager {
|
||||||
|
kvm, ram, device_memory,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn guest_ram(&self) -> &GuestRam {
|
||||||
|
&self.ram
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn kvm(&self) -> &Kvm {
|
||||||
|
&self.kvm
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn register_device_memory(&self, fd: RawFd, size: usize) -> Result<(u64, u32)> {
|
||||||
|
let mut devmem = self.device_memory.write().unwrap();
|
||||||
|
devmem.register(self.kvm(), fd, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unregister_device_memory(&self, slot: u32) -> Result<()> {
|
||||||
|
let mut devmem = self.device_memory.write().unwrap();
|
||||||
|
devmem.unregister(self.kvm(), slot)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct MemoryRegistration {
|
||||||
|
guest_addr: u64,
|
||||||
|
_mapping: Mapping,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MemoryRegistration {
|
||||||
|
fn new(guest_addr: u64, mapping: Mapping)-> Self {
|
||||||
|
MemoryRegistration { guest_addr, _mapping: mapping }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct DeviceMemory {
|
||||||
|
slots: BitVec,
|
||||||
|
mappings: HashMap<u32, MemoryRegistration>,
|
||||||
|
allocator: SystemAllocator,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DeviceMemory {
|
||||||
|
fn new(ram_region_count: usize, allocator: SystemAllocator) -> DeviceMemory {
|
||||||
|
let mut slots = BitVec::new();
|
||||||
|
for i in 0..ram_region_count {
|
||||||
|
slots.set_bit(i);
|
||||||
|
}
|
||||||
|
DeviceMemory {
|
||||||
|
slots, mappings: HashMap::new(), allocator
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn register(&mut self, kvm: &Kvm, fd: RawFd, size: usize) -> Result<(u64, u32)> {
|
||||||
|
let mapping = Mapping::new_from_fd(fd, size)
|
||||||
|
.map_err(Error::MappingFailed)?;
|
||||||
|
|
||||||
|
let (addr, slot) = self.allocate_addr_and_slot(size)?;
|
||||||
|
|
||||||
|
if let Err(e) = kvm.add_memory_region(slot, addr, mapping.address(), size) {
|
||||||
|
self.free_addr_and_slot(addr, slot);
|
||||||
|
Err(Error::RegisterMemoryFailed(e))
|
||||||
|
} else {
|
||||||
|
self.mappings.insert(slot, MemoryRegistration::new(addr, mapping));
|
||||||
|
Ok((addr >> 12, slot))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unregister(&mut self, kvm: &Kvm, slot: u32) -> Result<()> {
|
||||||
|
if let Some(registration) = self.mappings.remove(&slot) {
|
||||||
|
kvm.remove_memory_region(slot)
|
||||||
|
.map_err(Error::UnregisterMemoryFailed)?;
|
||||||
|
self.free_addr_and_slot(registration.guest_addr, slot);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn allocate_addr_and_slot(&mut self, size: usize) -> Result<(u64, u32)> {
|
||||||
|
let addr = self.allocator.allocate_device_memory(size)
|
||||||
|
.ok_or(Error::DeviceMemoryAllocFailed)?;
|
||||||
|
Ok((addr, self.allocate_slot()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn free_addr_and_slot(&mut self, addr: u64, slot: u32) {
|
||||||
|
self.allocator.free_device_memory(addr);
|
||||||
|
self.free_slot(slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn allocate_slot(&mut self) -> u32 {
|
||||||
|
let slot = self.slots.first_unset();
|
||||||
|
self.slots.set_bit(slot);
|
||||||
|
slot as u32
|
||||||
|
}
|
||||||
|
|
||||||
|
fn free_slot(&mut self, slot: u32) {
|
||||||
|
self.slots.clear_bit(slot as usize)
|
||||||
|
}
|
||||||
|
}
|
@ -1,13 +1,42 @@
|
|||||||
mod ram;
|
mod ram;
|
||||||
|
mod manager;
|
||||||
mod mmap;
|
mod mmap;
|
||||||
mod address;
|
mod address;
|
||||||
|
mod allocator;
|
||||||
|
|
||||||
|
pub use self::allocator::SystemAllocator;
|
||||||
pub use self::address::AddressRange;
|
pub use self::address::AddressRange;
|
||||||
pub use self::mmap::Mapping;
|
pub use self::mmap::Mapping;
|
||||||
pub use self::ram::GuestRam;
|
pub use self::ram::GuestRam;
|
||||||
pub use self::ram::{PCI_MMIO_RESERVED_BASE,HIMEM_BASE};
|
pub use self::ram::{PCI_MMIO_RESERVED_BASE,HIMEM_BASE};
|
||||||
|
pub use manager::MemoryManager;
|
||||||
|
use crate::vm::Error as VmError;
|
||||||
|
use std::{result, fmt};
|
||||||
|
|
||||||
pub const KVM_KERNEL_LOAD_ADDRESS: u64 = 0x1000000;
|
pub const KVM_KERNEL_LOAD_ADDRESS: u64 = 0x1000000;
|
||||||
pub const KERNEL_CMDLINE_ADDRESS: u64 = 0x20000;
|
pub const KERNEL_CMDLINE_ADDRESS: u64 = 0x20000;
|
||||||
pub const KERNEL_ZERO_PAGE: u64 = 0x7000;
|
pub const KERNEL_ZERO_PAGE: u64 = 0x7000;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Error {
|
||||||
|
DeviceMemoryAllocFailed,
|
||||||
|
MappingFailed(VmError),
|
||||||
|
RegisterMemoryFailed(VmError),
|
||||||
|
UnregisterMemoryFailed(VmError),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Error {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
use Error::*;
|
||||||
|
match self {
|
||||||
|
DeviceMemoryAllocFailed => write!(f, "failed to allocate memory for device"),
|
||||||
|
MappingFailed(e) => write!(f, "failed to create memory mapping for device memory: {}", e),
|
||||||
|
RegisterMemoryFailed(e) => write!(f, "failed to register memory for device memory: {}", e),
|
||||||
|
UnregisterMemoryFailed(e) => write!(f, "failed to unregister memory for device memory: {}", e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type Result<T> = result::Result<T, Error>;
|
||||||
|
|
||||||
|
|
||||||
|
@ -31,6 +31,10 @@ impl GuestRam {
|
|||||||
self.ram_size
|
self.ram_size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn region_count(&self) -> usize {
|
||||||
|
self.regions.len()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn write_bytes(&self, guest_address: u64, bytes: &[u8]) -> Result<()> {
|
pub fn write_bytes(&self, guest_address: u64, bytes: &[u8]) -> Result<()> {
|
||||||
let region = self.find_region(guest_address, bytes.len())?;
|
let region = self.find_region(guest_address, bytes.len())?;
|
||||||
region.write_bytes(guest_address, bytes)
|
region.write_bytes(guest_address, bytes)
|
||||||
@ -41,7 +45,6 @@ impl GuestRam {
|
|||||||
region.read_bytes(guest_address, bytes)
|
region.read_bytes(guest_address, bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn slice(&self, guest_address: u64, size: usize) -> Result<&[u8]> {
|
pub fn slice(&self, guest_address: u64, size: usize) -> Result<&[u8]> {
|
||||||
let region = self.find_region(guest_address, size)?;
|
let region = self.find_region(guest_address, size)?;
|
||||||
region.slice(guest_address, size)
|
region.slice(guest_address, size)
|
||||||
@ -56,11 +59,19 @@ impl GuestRam {
|
|||||||
let region = self.find_region(guest_address, mem::size_of::<T>())?;
|
let region = self.find_region(guest_address, mem::size_of::<T>())?;
|
||||||
region.write_int(guest_address, val)
|
region.write_int(guest_address, val)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_int<T: Serializable>(&self, guest_address: u64) -> Result<T> {
|
pub fn read_int<T: Serializable>(&self, guest_address: u64) -> Result<T> {
|
||||||
let region = self.find_region(guest_address, mem::size_of::<T>())?;
|
let region = self.find_region(guest_address, mem::size_of::<T>())?;
|
||||||
region.read_int(guest_address)
|
region.read_int(guest_address)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn end_addr(&self) -> u64 {
|
||||||
|
self.regions.iter()
|
||||||
|
.max_by_key(|r| r.guest_range.end())
|
||||||
|
.map_or(0, |r| r.guest_range.end())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_valid_range(&self, guest_address: u64, size: usize) -> bool {
|
pub fn is_valid_range(&self, guest_address: u64, size: usize) -> bool {
|
||||||
self.find_region(guest_address, size).is_ok()
|
self.find_region(guest_address, size).is_ok()
|
||||||
}
|
}
|
||||||
@ -73,7 +84,7 @@ impl GuestRam {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn add_region(regions: &mut Vec<MemoryRegion>, base: u64, size: usize, kvm: &Kvm) -> Result<()> {
|
fn add_region(regions: &mut Vec<MemoryRegion>, base: u64, size: usize, kvm: &Kvm) -> Result<()> {
|
||||||
let slot = regions.len();
|
let slot = regions.len() as u32;
|
||||||
let mr = MemoryRegion::new(base, size)?;
|
let mr = MemoryRegion::new(base, size)?;
|
||||||
kvm.add_memory_region(slot, base, mr.mapping.address(), size)
|
kvm.add_memory_region(slot, base, mr.mapping.address(), size)
|
||||||
.map_err(|e| Error::new(ErrorKind::RegisterMemoryFailed, e))?;
|
.map_err(|e| Error::new(ErrorKind::RegisterMemoryFailed, e))?;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use std::sync::{Arc,RwLock};
|
use std::sync::{Arc,RwLock};
|
||||||
use crate::vm::io::IoDispatcher;
|
use crate::vm::io::IoDispatcher;
|
||||||
use crate::kvm::Kvm;
|
use crate::kvm::Kvm;
|
||||||
use crate::memory::{GuestRam,AddressRange};
|
use crate::memory::{AddressRange, MemoryManager};
|
||||||
use super::{VirtioDevice,VirtioDeviceOps,PciIrq};
|
use super::{VirtioDevice,VirtioDeviceOps,PciIrq};
|
||||||
use super::consts::*;
|
use super::consts::*;
|
||||||
use super::pci::PciBus;
|
use super::pci::PciBus;
|
||||||
@ -10,14 +10,14 @@ use crate::vm::Result;
|
|||||||
|
|
||||||
pub struct VirtioBus {
|
pub struct VirtioBus {
|
||||||
kvm: Kvm,
|
kvm: Kvm,
|
||||||
memory: GuestRam,
|
memory: MemoryManager,
|
||||||
io_dispatcher: Arc<IoDispatcher>,
|
io_dispatcher: Arc<IoDispatcher>,
|
||||||
pci_bus: Arc<RwLock<PciBus>>,
|
pci_bus: Arc<RwLock<PciBus>>,
|
||||||
devices: Vec<Arc<RwLock<VirtioDevice>>>,
|
devices: Vec<Arc<RwLock<VirtioDevice>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VirtioBus {
|
impl VirtioBus {
|
||||||
pub fn new(memory: GuestRam, io_dispatcher: Arc<IoDispatcher>, kvm: Kvm) -> VirtioBus {
|
pub fn new(memory: MemoryManager, io_dispatcher: Arc<IoDispatcher>, kvm: Kvm) -> VirtioBus {
|
||||||
VirtioBus {
|
VirtioBus {
|
||||||
kvm,
|
kvm,
|
||||||
memory,
|
memory,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use std::sync::{Arc,RwLock};
|
use std::sync::{Arc,RwLock};
|
||||||
use std::ops::DerefMut;
|
use std::ops::DerefMut;
|
||||||
|
|
||||||
use crate::memory::{GuestRam,AddressRange};
|
use crate::memory::{AddressRange, MemoryManager};
|
||||||
use super::bus::VirtioDeviceConfig;
|
use super::bus::VirtioDeviceConfig;
|
||||||
use super::VirtQueue;
|
use super::VirtQueue;
|
||||||
use super::config::VirtQueueConfig;
|
use super::config::VirtQueueConfig;
|
||||||
@ -14,11 +14,11 @@ pub trait VirtioDeviceOps: Send+Sync {
|
|||||||
fn enable_features(&mut self, bits: u64) -> bool { let _ = bits; true }
|
fn enable_features(&mut self, bits: u64) -> bool { let _ = bits; true }
|
||||||
fn write_config(&mut self, offset: usize, size: usize, val: u64) { let (_,_,_) = (offset, size, val); }
|
fn write_config(&mut self, offset: usize, size: usize, val: u64) { let (_,_,_) = (offset, size, val); }
|
||||||
fn read_config(&mut self, offset: usize, size: usize) -> u64 { let (_,_) = (offset, size); 0 }
|
fn read_config(&mut self, offset: usize, size: usize) -> u64 { let (_,_) = (offset, size); 0 }
|
||||||
fn start(&mut self, memory: GuestRam, queues: Vec<VirtQueue>);
|
fn start(&mut self, memory: &MemoryManager, queues: Vec<VirtQueue>);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct VirtioDevice {
|
pub struct VirtioDevice {
|
||||||
memory: GuestRam,
|
memory: MemoryManager,
|
||||||
vq_config: VirtQueueConfig,
|
vq_config: VirtQueueConfig,
|
||||||
common_cfg_mmio: AddressRange,
|
common_cfg_mmio: AddressRange,
|
||||||
isr_mmio: AddressRange,
|
isr_mmio: AddressRange,
|
||||||
@ -43,10 +43,10 @@ fn get_hi32(val: u64) -> u32 { (val >> 32) as u32 }
|
|||||||
|
|
||||||
|
|
||||||
impl VirtioDevice {
|
impl VirtioDevice {
|
||||||
pub fn new(memory: GuestRam, config: &VirtioDeviceConfig) -> Result<Arc<RwLock<VirtioDevice>>> {
|
pub fn new(memory: MemoryManager, config: &VirtioDeviceConfig) -> Result<Arc<RwLock<VirtioDevice>>> {
|
||||||
Ok(Arc::new(RwLock::new(VirtioDevice {
|
Ok(Arc::new(RwLock::new(VirtioDevice {
|
||||||
memory: memory.clone(),
|
memory: memory.clone(),
|
||||||
vq_config: VirtQueueConfig::new(&memory.clone(),&config)?,
|
vq_config: VirtQueueConfig::new(memory.guest_ram(),&config)?,
|
||||||
common_cfg_mmio: config.common_cfg_mmio(),
|
common_cfg_mmio: config.common_cfg_mmio(),
|
||||||
isr_mmio: config.isr_mmio(),
|
isr_mmio: config.isr_mmio(),
|
||||||
notify_mmio: config.notify_mmio(),
|
notify_mmio: config.notify_mmio(),
|
||||||
@ -85,8 +85,8 @@ impl VirtioDevice {
|
|||||||
let new_bits = val & !self.status;
|
let new_bits = val & !self.status;
|
||||||
|
|
||||||
if new_bits & VIRTIO_CONFIG_S_DRIVER_OK != 0 {
|
if new_bits & VIRTIO_CONFIG_S_DRIVER_OK != 0 {
|
||||||
match self.vq_config.create_queues(&self.memory) {
|
match self.vq_config.create_queues(self.memory.guest_ram()) {
|
||||||
Ok(queues) => self.with_ops(|ops| ops.start(self.memory.clone(), queues)),
|
Ok(queues) => self.with_ops(|ops| ops.start(&self.memory, queues)),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("creating virtqueues failed {}", e);
|
println!("creating virtqueues failed {}", e);
|
||||||
self.status |= VIRTIO_CONFIG_S_NEEDS_RESET;
|
self.status |= VIRTIO_CONFIG_S_NEEDS_RESET;
|
||||||
|
@ -8,7 +8,7 @@ use self::io::IoDispatcher;
|
|||||||
use crate::virtio::VirtioBus;
|
use crate::virtio::VirtioBus;
|
||||||
use crate::devices;
|
use crate::devices;
|
||||||
|
|
||||||
use crate::memory::{GuestRam,KVM_KERNEL_LOAD_ADDRESS};
|
use crate::memory::{GuestRam, KVM_KERNEL_LOAD_ADDRESS, MemoryManager, SystemAllocator, AddressRange};
|
||||||
use crate::kvm::*;
|
use crate::kvm::*;
|
||||||
|
|
||||||
|
|
||||||
@ -63,7 +63,7 @@ impl VmConfig {
|
|||||||
}
|
}
|
||||||
pub struct Vm {
|
pub struct Vm {
|
||||||
kvm: Kvm,
|
kvm: Kvm,
|
||||||
memory: GuestRam,
|
memory: MemoryManager,
|
||||||
io_dispatcher: Arc<IoDispatcher>,
|
io_dispatcher: Arc<IoDispatcher>,
|
||||||
_virtio: VirtioBus,
|
_virtio: VirtioBus,
|
||||||
}
|
}
|
||||||
@ -80,6 +80,14 @@ static REQUIRED_EXTENSIONS: &[u32] = &[
|
|||||||
KVM_CAP_IOEVENTFD,
|
KVM_CAP_IOEVENTFD,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
fn get_base_dev_pfn(mem_size: u64) -> u64 {
|
||||||
|
// Put device memory at a 2MB boundary after physical memory or 4gb, whichever is greater.
|
||||||
|
const MB: u64 = 1024 * 1024;
|
||||||
|
const GB: u64 = 1024 * MB;
|
||||||
|
let mem_size_round_2mb = (mem_size + 2 * MB - 1) / (2 * MB) * (2 * MB);
|
||||||
|
std::cmp::max(mem_size_round_2mb, 4 * GB) / 4096
|
||||||
|
}
|
||||||
|
|
||||||
impl Vm {
|
impl Vm {
|
||||||
pub fn open(config: VmConfig) -> Result<Vm> {
|
pub fn open(config: VmConfig) -> Result<Vm> {
|
||||||
let mut kvm = Kvm::open(&REQUIRED_EXTENSIONS)?;
|
let mut kvm = Kvm::open(&REQUIRED_EXTENSIONS)?;
|
||||||
@ -87,16 +95,20 @@ impl Vm {
|
|||||||
kvm.set_tss_addr(0xFFFbd000)?;
|
kvm.set_tss_addr(0xFFFbd000)?;
|
||||||
kvm.create_pit2()?;
|
kvm.create_pit2()?;
|
||||||
|
|
||||||
let memory = GuestRam::new(config.ram_size, &kvm)?;
|
let ram = GuestRam::new(config.ram_size, &kvm)?;
|
||||||
|
let dev_addr_start = get_base_dev_pfn(config.ram_size as u64) * 4096;
|
||||||
|
let dev_addr_size = u64::max_value() - dev_addr_start;
|
||||||
|
let allocator = SystemAllocator::new(AddressRange::new(dev_addr_start,dev_addr_size as usize));
|
||||||
|
let memory = MemoryManager::new(kvm.clone(), ram, allocator);
|
||||||
|
|
||||||
kvm.create_irqchip()?;
|
kvm.create_irqchip()?;
|
||||||
|
|
||||||
let verbose = env::args().any(|arg| arg == "-v");
|
let verbose = env::args().any(|arg| arg == "-v");
|
||||||
let cmdline = KernelCmdLine::new_default(verbose);
|
let cmdline = KernelCmdLine::new_default(verbose);
|
||||||
|
|
||||||
cmdline.write_to_memory(&memory)?;
|
cmdline.write_to_memory(memory.guest_ram())?;
|
||||||
let path = PathBuf::from(&config.kernel_path);
|
let path = PathBuf::from(&config.kernel_path);
|
||||||
setup::kernel::load_pm_kernel(&memory, &path, cmdline.address(), cmdline.size())?;
|
setup::kernel::load_pm_kernel(memory.guest_ram(), &path, cmdline.address(), cmdline.size())?;
|
||||||
|
|
||||||
let io_dispatch = IoDispatcher::new();
|
let io_dispatch = IoDispatcher::new();
|
||||||
|
|
||||||
@ -126,8 +138,8 @@ impl Vm {
|
|||||||
pub fn start(&self) -> Result<()> {
|
pub fn start(&self) -> Result<()> {
|
||||||
let mut handles = Vec::new();
|
let mut handles = Vec::new();
|
||||||
for vcpu in self.kvm.get_vcpus() {
|
for vcpu in self.kvm.get_vcpus() {
|
||||||
setup::cpu::setup_protected_mode(&vcpu, KVM_KERNEL_LOAD_ADDRESS + 0x200, &self.memory)?;
|
setup::cpu::setup_protected_mode(&vcpu, KVM_KERNEL_LOAD_ADDRESS + 0x200, self.memory.guest_ram())?;
|
||||||
let mut run_area = KvmRunArea::new(vcpu, self.io_dispatcher.clone())?;
|
let mut run_area = KvmRunArea::new(vcpu, shutdown.clone(), self.io_dispatcher.clone())?;
|
||||||
let h = thread::spawn(move || run_area.run());
|
let h = thread::spawn(move || run_area.run());
|
||||||
handles.push(h);
|
handles.push(h);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user