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