1*40314b30SXiaoye Zheng use crate::arch::kvm::vmx::vcpu::VmxVcpu; 2*40314b30SXiaoye Zheng use crate::libs::mutex::Mutex; 3*40314b30SXiaoye Zheng use crate::syscall::SystemError; 4*40314b30SXiaoye Zheng use crate::{arch::KVMArch, kdebug}; 5*40314b30SXiaoye Zheng use alloc::sync::Arc; 6*40314b30SXiaoye Zheng use alloc::vec::Vec; 7*40314b30SXiaoye Zheng 8*40314b30SXiaoye Zheng // use super::HOST_STACK_SIZE; 9*40314b30SXiaoye Zheng use super::host_mem::{ 10*40314b30SXiaoye Zheng KvmMemoryChange, KvmMemorySlot, KvmMemorySlots, KvmUserspaceMemoryRegion, 11*40314b30SXiaoye Zheng KVM_ADDRESS_SPACE_NUM, KVM_MEM_LOG_DIRTY_PAGES, KVM_MEM_MAX_NR_PAGES, KVM_MEM_READONLY, 12*40314b30SXiaoye Zheng KVM_MEM_SLOTS_NUM, KVM_USER_MEM_SLOTS, PAGE_SHIFT, 13*40314b30SXiaoye Zheng }; 14*40314b30SXiaoye Zheng use crate::arch::kvm::vmx::vmcs::PAGE_SIZE; 15*40314b30SXiaoye Zheng // use crate::kdebug; 16*40314b30SXiaoye Zheng 17*40314b30SXiaoye Zheng #[derive(Debug, Clone)] 18*40314b30SXiaoye Zheng pub struct Vm { 19*40314b30SXiaoye Zheng pub id: usize, 20*40314b30SXiaoye Zheng // vcpu config 21*40314b30SXiaoye Zheng pub nr_vcpus: u32, /* Number of cpus to run */ 22*40314b30SXiaoye Zheng pub vcpu: Vec<Arc<Mutex<VmxVcpu>>>, 23*40314b30SXiaoye Zheng // memory config 24*40314b30SXiaoye Zheng pub nr_mem_slots: u32, /* Number of memory slots in each address space */ 25*40314b30SXiaoye Zheng pub memslots: [KvmMemorySlots; KVM_ADDRESS_SPACE_NUM], 26*40314b30SXiaoye Zheng // arch related config 27*40314b30SXiaoye Zheng pub arch: KVMArch, 28*40314b30SXiaoye Zheng } 29*40314b30SXiaoye Zheng 30*40314b30SXiaoye Zheng impl Vm { 31*40314b30SXiaoye Zheng pub fn new(id: usize) -> Result<Self, SystemError> { 32*40314b30SXiaoye Zheng let vcpu = Vec::new(); 33*40314b30SXiaoye Zheng // Allocate stack for vm-exit handlers and fill it with garbage data 34*40314b30SXiaoye Zheng let instance = Self { 35*40314b30SXiaoye Zheng id, 36*40314b30SXiaoye Zheng nr_vcpus: 0, 37*40314b30SXiaoye Zheng vcpu, 38*40314b30SXiaoye Zheng nr_mem_slots: KVM_MEM_SLOTS_NUM, 39*40314b30SXiaoye Zheng memslots: [KvmMemorySlots::default(); KVM_ADDRESS_SPACE_NUM], 40*40314b30SXiaoye Zheng arch: Default::default(), 41*40314b30SXiaoye Zheng }; 42*40314b30SXiaoye Zheng Ok(instance) 43*40314b30SXiaoye Zheng } 44*40314b30SXiaoye Zheng 45*40314b30SXiaoye Zheng /// Allocate some memory and give it an address in the guest physical address space. 46*40314b30SXiaoye Zheng pub fn set_user_memory_region( 47*40314b30SXiaoye Zheng &mut self, 48*40314b30SXiaoye Zheng mem: &KvmUserspaceMemoryRegion, 49*40314b30SXiaoye Zheng ) -> Result<(), SystemError> { 50*40314b30SXiaoye Zheng kdebug!("set_user_memory_region"); 51*40314b30SXiaoye Zheng let id: u16 = mem.slot as u16; // slot id 52*40314b30SXiaoye Zheng let as_id = mem.slot >> 16; // address space id 53*40314b30SXiaoye Zheng kdebug!("id={}, as_id={}", id, as_id); 54*40314b30SXiaoye Zheng 55*40314b30SXiaoye Zheng // 检查slot是否合法 56*40314b30SXiaoye Zheng if mem.slot as usize >= self.nr_mem_slots as usize { 57*40314b30SXiaoye Zheng return Err(SystemError::EINVAL); 58*40314b30SXiaoye Zheng } 59*40314b30SXiaoye Zheng // 检查flags是否合法 60*40314b30SXiaoye Zheng self.check_memory_region_flag(mem)?; 61*40314b30SXiaoye Zheng // 内存大小和地址必须是页对齐的 62*40314b30SXiaoye Zheng if (mem.memory_size & (PAGE_SIZE - 1) as u64) != 0 63*40314b30SXiaoye Zheng || (mem.guest_phys_addr & (PAGE_SIZE - 1) as u64) != 0 64*40314b30SXiaoye Zheng { 65*40314b30SXiaoye Zheng return Err(SystemError::EINVAL); 66*40314b30SXiaoye Zheng } 67*40314b30SXiaoye Zheng // 检查地址空间是否合法 68*40314b30SXiaoye Zheng if as_id >= (KVM_ADDRESS_SPACE_NUM as u32) || id >= KVM_MEM_SLOTS_NUM as u16 { 69*40314b30SXiaoye Zheng return Err(SystemError::EINVAL); 70*40314b30SXiaoye Zheng } 71*40314b30SXiaoye Zheng // if mem.memory_size < 0 { 72*40314b30SXiaoye Zheng // return Err(SystemError::EINVAL); 73*40314b30SXiaoye Zheng // } 74*40314b30SXiaoye Zheng let slot = &self.memslots[as_id as usize].memslots[id as usize]; 75*40314b30SXiaoye Zheng let base_gfn = mem.guest_phys_addr >> PAGE_SHIFT; 76*40314b30SXiaoye Zheng let npages = mem.memory_size >> PAGE_SHIFT; 77*40314b30SXiaoye Zheng if npages > KVM_MEM_MAX_NR_PAGES as u64 { 78*40314b30SXiaoye Zheng return Err(SystemError::EINVAL); 79*40314b30SXiaoye Zheng } 80*40314b30SXiaoye Zheng let change: KvmMemoryChange; 81*40314b30SXiaoye Zheng 82*40314b30SXiaoye Zheng let old_slot = slot; 83*40314b30SXiaoye Zheng let mut new_slot = KvmMemorySlot { 84*40314b30SXiaoye Zheng base_gfn, // 虚机内存区间起始物理页框号 85*40314b30SXiaoye Zheng npages, // 虚机内存区间页数,即内存区间的大小 86*40314b30SXiaoye Zheng // dirty_bitmap: old_slot.dirty_bitmap, 87*40314b30SXiaoye Zheng userspace_addr: mem.userspace_addr, // 虚机内存区间对应的主机虚拟地址 88*40314b30SXiaoye Zheng flags: mem.flags, // 虚机内存区间属性 89*40314b30SXiaoye Zheng id, // 虚机内存区间id 90*40314b30SXiaoye Zheng }; 91*40314b30SXiaoye Zheng 92*40314b30SXiaoye Zheng // 判断新memoryslot的类型 93*40314b30SXiaoye Zheng if npages != 0 { 94*40314b30SXiaoye Zheng //映射内存有大小,不是删除内存条 95*40314b30SXiaoye Zheng if old_slot.npages == 0 { 96*40314b30SXiaoye Zheng //内存槽号没有虚拟内存条,意味内存新创建 97*40314b30SXiaoye Zheng change = KvmMemoryChange::Create; 98*40314b30SXiaoye Zheng } else { 99*40314b30SXiaoye Zheng //修改已存在的内存,表示修改标志或者平移映射地址 100*40314b30SXiaoye Zheng // 检查内存条是否可以修改 101*40314b30SXiaoye Zheng if mem.userspace_addr != old_slot.userspace_addr 102*40314b30SXiaoye Zheng || npages != old_slot.npages 103*40314b30SXiaoye Zheng || (new_slot.flags ^ old_slot.flags & KVM_MEM_READONLY) != 0 104*40314b30SXiaoye Zheng { 105*40314b30SXiaoye Zheng return Err(SystemError::EINVAL); 106*40314b30SXiaoye Zheng } 107*40314b30SXiaoye Zheng if new_slot.base_gfn != old_slot.base_gfn { 108*40314b30SXiaoye Zheng //guest地址不同,内存条平移 109*40314b30SXiaoye Zheng change = KvmMemoryChange::Move; 110*40314b30SXiaoye Zheng } else if new_slot.flags != old_slot.flags { 111*40314b30SXiaoye Zheng //内存条标志不同,修改标志 112*40314b30SXiaoye Zheng change = KvmMemoryChange::FlagsOnly; 113*40314b30SXiaoye Zheng } else { 114*40314b30SXiaoye Zheng return Ok(()); 115*40314b30SXiaoye Zheng } 116*40314b30SXiaoye Zheng } 117*40314b30SXiaoye Zheng } else { 118*40314b30SXiaoye Zheng if old_slot.npages == 0 { 119*40314b30SXiaoye Zheng //内存槽号没有虚拟内存条,不可以删除 120*40314b30SXiaoye Zheng return Err(SystemError::EINVAL); 121*40314b30SXiaoye Zheng } 122*40314b30SXiaoye Zheng //申请插入的内存为0,而内存槽上有内存,意味删除 123*40314b30SXiaoye Zheng change = KvmMemoryChange::Delete; 124*40314b30SXiaoye Zheng new_slot.base_gfn = 0; 125*40314b30SXiaoye Zheng new_slot.flags = 0; 126*40314b30SXiaoye Zheng } 127*40314b30SXiaoye Zheng 128*40314b30SXiaoye Zheng if change == KvmMemoryChange::Create || change == KvmMemoryChange::Move { 129*40314b30SXiaoye Zheng // 检查内存区域是否重叠 130*40314b30SXiaoye Zheng for i in 0..KVM_MEM_SLOTS_NUM { 131*40314b30SXiaoye Zheng let memslot = &self.memslots[as_id as usize].memslots[i as usize]; 132*40314b30SXiaoye Zheng if memslot.id == id || memslot.id as u32 >= KVM_USER_MEM_SLOTS { 133*40314b30SXiaoye Zheng continue; 134*40314b30SXiaoye Zheng } 135*40314b30SXiaoye Zheng // 当前已有的slot与new在guest物理地址上有交集 136*40314b30SXiaoye Zheng if !(base_gfn + npages <= memslot.base_gfn 137*40314b30SXiaoye Zheng || memslot.base_gfn + memslot.npages <= base_gfn) 138*40314b30SXiaoye Zheng { 139*40314b30SXiaoye Zheng return Err(SystemError::EEXIST); 140*40314b30SXiaoye Zheng } 141*40314b30SXiaoye Zheng } 142*40314b30SXiaoye Zheng } 143*40314b30SXiaoye Zheng 144*40314b30SXiaoye Zheng if !(new_slot.flags & KVM_MEM_LOG_DIRTY_PAGES != 0) { 145*40314b30SXiaoye Zheng // new_slot.dirty_bitmap = 0; 146*40314b30SXiaoye Zheng } 147*40314b30SXiaoye Zheng 148*40314b30SXiaoye Zheng // 根据flags的值,决定是否创建内存脏页 149*40314b30SXiaoye Zheng // if (new_slot.flags & KVM_MEM_LOG_DIRTY_PAGES)!=0 && new_slot.dirty_bitmap == 0 { 150*40314b30SXiaoye Zheng // let type_size = core::mem::size_of::<u64>() as u64; 151*40314b30SXiaoye Zheng // let dirty_bytes = 2 * ((new_slot.npages+type_size-1) / type_size) / 8; 152*40314b30SXiaoye Zheng // new_slot.dirty_bitmap = Box::new(vec![0; dirty_bytes as u8]); 153*40314b30SXiaoye Zheng // } 154*40314b30SXiaoye Zheng if change == KvmMemoryChange::Create { 155*40314b30SXiaoye Zheng new_slot.userspace_addr = mem.userspace_addr; 156*40314b30SXiaoye Zheng let mut memslots = self.memslots[as_id as usize].memslots.clone(); 157*40314b30SXiaoye Zheng memslots[id as usize] = new_slot; 158*40314b30SXiaoye Zheng self.memslots[as_id as usize].memslots = memslots; 159*40314b30SXiaoye Zheng self.memslots[as_id as usize].used_slots += 1; 160*40314b30SXiaoye Zheng // KVMArch::kvm_arch_create_memslot(&mut new_slot, npages); 161*40314b30SXiaoye Zheng // KVMArch::kvm_arch_commit_memory_region(mem, &new_slot, old_slot, change); 162*40314b30SXiaoye Zheng } 163*40314b30SXiaoye Zheng // TODO--KvmMemoryChange::Delete & Move 164*40314b30SXiaoye Zheng Ok(()) 165*40314b30SXiaoye Zheng } 166*40314b30SXiaoye Zheng 167*40314b30SXiaoye Zheng fn check_memory_region_flag(&self, mem: &KvmUserspaceMemoryRegion) -> Result<(), SystemError> { 168*40314b30SXiaoye Zheng let valid_flags = KVM_MEM_LOG_DIRTY_PAGES; 169*40314b30SXiaoye Zheng // 除了valid_flags之外的flags被置1了,就返回错误 170*40314b30SXiaoye Zheng if mem.flags & !valid_flags != 0 { 171*40314b30SXiaoye Zheng return Err(SystemError::EINVAL); 172*40314b30SXiaoye Zheng } 173*40314b30SXiaoye Zheng Ok(()) 174*40314b30SXiaoye Zheng } 175*40314b30SXiaoye Zheng } 176