1 // Copyright © 2020 Intel Corporation 2 // 3 // SPDX-License-Identifier: Apache-2.0 4 // 5 6 use crate::MigratableError; 7 use vm_memory::ByteValued; 8 9 // Migration protocol 10 // 1: Source establishes communication with destination (file socket or TCP connection.) 11 // (The establishment is out of scope.) 12 // 2: Source -> Dest : send "start command" 13 // 3: Dest -> Source : sends "ok response" when read to accept state data 14 // 4: Source -> Dest : sends "config command" followed by config data, length 15 // in command is length of config data 16 // 5: Dest -> Source : sends "ok response" when ready to accept memory data 17 // 6: Source -> Dest : send "memory command" followed by table of u64 pairs (GPA, size) 18 // followed by the memory described in those pairs. 19 // !! length is size of table i.e. 16 * number of ranges !! 20 // 7: Dest -> Source : sends "ok response" when ready to accept more memory data 21 // 8..(n-4): Repeat steps 6 and 7 until source has no more memory to send 22 // (n-3): Source -> Dest : sends "state command" followed by state data, length 23 // in command is length of config data 24 // (n-2): Dest -> Source : sends "ok response" 25 // (n-1): Source -> Dest : send "complete command" 26 // n: Dest -> Source: sends "ok response" 27 28 // The destination can at any time send an "error response" to cancel 29 // The source can at any time send an "abandon request" to cancel 30 31 use std::io::{Read, Write}; 32 33 #[repr(u16)] 34 #[derive(Copy, Clone)] 35 pub enum Command { 36 Invalid, 37 Start, 38 Config, 39 State, 40 Memory, 41 Complete, 42 Abandon, 43 } 44 45 impl Default for Command { 46 fn default() -> Self { 47 Self::Invalid 48 } 49 } 50 51 #[repr(C)] 52 #[derive(Default, Copy, Clone)] 53 pub struct Request { 54 command: Command, 55 padding: [u8; 6], 56 length: u64, // Length of payload for command excluding the Request struct 57 } 58 59 impl Request { 60 pub fn new(command: Command, length: u64) -> Self { 61 Self { 62 command, 63 length, 64 ..Default::default() 65 } 66 } 67 68 pub fn start() -> Self { 69 Self::new(Command::Start, 0) 70 } 71 72 pub fn state(length: u64) -> Self { 73 Self::new(Command::State, length) 74 } 75 76 pub fn config(length: u64) -> Self { 77 Self::new(Command::Config, length) 78 } 79 80 pub fn memory(length: u64) -> Self { 81 Self::new(Command::Memory, length) 82 } 83 84 pub fn complete() -> Self { 85 Self::new(Command::Complete, 0) 86 } 87 88 pub fn abandon() -> Self { 89 Self::new(Command::Abandon, 0) 90 } 91 92 pub fn command(&self) -> Command { 93 self.command 94 } 95 96 pub fn length(&self) -> u64 { 97 self.length 98 } 99 100 pub fn read_from(fd: &mut dyn Read) -> Result<Request, MigratableError> { 101 let mut request = Request::default(); 102 fd.read_exact(Self::as_mut_slice(&mut request)) 103 .map_err(MigratableError::MigrateSocket)?; 104 105 Ok(request) 106 } 107 108 pub fn write_to(&self, fd: &mut dyn Write) -> Result<(), MigratableError> { 109 fd.write_all(Self::as_slice(self)) 110 .map_err(MigratableError::MigrateSocket) 111 } 112 } 113 114 unsafe impl ByteValued for Request {} 115 116 #[repr(u16)] 117 #[derive(Copy, Clone, PartialEq)] 118 pub enum Status { 119 Invalid, 120 Ok, 121 Error, 122 } 123 124 impl Default for Status { 125 fn default() -> Self { 126 Self::Invalid 127 } 128 } 129 130 #[repr(C)] 131 #[derive(Default, Copy, Clone)] 132 pub struct Response { 133 status: Status, 134 padding: [u8; 6], 135 length: u64, // Length of payload for command excluding the Response struct 136 } 137 138 impl Response { 139 pub fn new(status: Status, length: u64) -> Self { 140 Self { 141 status, 142 length, 143 ..Default::default() 144 } 145 } 146 147 pub fn ok() -> Self { 148 Self::new(Status::Ok, 0) 149 } 150 151 pub fn error() -> Self { 152 Self::new(Status::Error, 0) 153 } 154 155 pub fn status(&self) -> Status { 156 self.status 157 } 158 159 pub fn read_from(fd: &mut dyn Read) -> Result<Response, MigratableError> { 160 let mut response = Response::default(); 161 fd.read_exact(Self::as_mut_slice(&mut response)) 162 .map_err(MigratableError::MigrateSocket)?; 163 164 Ok(response) 165 } 166 167 pub fn write_to(&self, fd: &mut dyn Write) -> Result<(), MigratableError> { 168 fd.write_all(Self::as_slice(self)) 169 .map_err(MigratableError::MigrateSocket) 170 } 171 } 172 173 unsafe impl ByteValued for Response {} 174 175 #[repr(C)] 176 pub struct MemoryRange { 177 pub gpa: u64, 178 pub length: u64, 179 } 180 181 #[derive(Default)] 182 pub struct MemoryRangeTable { 183 data: Vec<MemoryRange>, 184 } 185 186 impl MemoryRangeTable { 187 pub fn from_bitmap(bitmap: Vec<u64>, start_addr: u64) -> Self { 188 let page_size = 4096; 189 let mut table = MemoryRangeTable::default(); 190 let mut entry: Option<MemoryRange> = None; 191 for (i, block) in bitmap.iter().enumerate() { 192 for j in 0..64 { 193 let is_page_dirty = ((block >> j) & 1u64) != 0u64; 194 let page_offset = ((i * 64) + j) as u64 * page_size; 195 if is_page_dirty { 196 if let Some(entry) = &mut entry { 197 entry.length += page_size; 198 } else { 199 entry = Some(MemoryRange { 200 gpa: start_addr + page_offset, 201 length: page_size, 202 }); 203 } 204 } else if let Some(entry) = entry.take() { 205 table.push(entry); 206 } 207 } 208 } 209 if let Some(entry) = entry.take() { 210 table.push(entry); 211 } 212 213 table 214 } 215 216 pub fn regions(&self) -> &[MemoryRange] { 217 &self.data 218 } 219 220 pub fn push(&mut self, range: MemoryRange) { 221 self.data.push(range) 222 } 223 224 pub fn read_from(fd: &mut dyn Read, length: u64) -> Result<MemoryRangeTable, MigratableError> { 225 assert!(length as usize % std::mem::size_of::<MemoryRange>() == 0); 226 227 let mut data = Vec::with_capacity(length as usize / (std::mem::size_of::<MemoryRange>())); 228 unsafe { 229 data.set_len(length as usize / (std::mem::size_of::<MemoryRange>())); 230 } 231 fd.read_exact(unsafe { 232 std::slice::from_raw_parts_mut( 233 data.as_ptr() as *mut MemoryRange as *mut u8, 234 length as usize, 235 ) 236 }) 237 .map_err(MigratableError::MigrateSocket)?; 238 239 Ok(Self { data }) 240 } 241 242 pub fn length(&self) -> u64 { 243 (std::mem::size_of::<MemoryRange>() * self.data.len()) as u64 244 } 245 246 pub fn write_to(&self, fd: &mut dyn Write) -> Result<(), MigratableError> { 247 fd.write_all(unsafe { 248 std::slice::from_raw_parts( 249 self.data.as_ptr() as *const MemoryRange as *const u8, 250 self.length() as usize, 251 ) 252 }) 253 .map_err(MigratableError::MigrateSocket) 254 } 255 256 pub fn is_empty(&self) -> bool { 257 self.data.is_empty() 258 } 259 260 pub fn extend(&mut self, table: Self) { 261 self.data.extend(table.data) 262 } 263 264 pub fn new_from_tables(tables: Vec<Self>) -> Self { 265 let mut data = Vec::new(); 266 for table in tables { 267 data.extend(table.data); 268 } 269 Self { data } 270 } 271 } 272