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