1aa98589bSRob Bradford // Copyright © 2020 Intel Corporation 2aa98589bSRob Bradford // 3aa98589bSRob Bradford // SPDX-License-Identifier: Apache-2.0 4aa98589bSRob Bradford // 5aa98589bSRob Bradford 62569621cSSebastien Boeuf use std::io::{Read, Write}; 7*88a9f799SRob Bradford 8*88a9f799SRob Bradford use serde::{Deserialize, Serialize}; 98e9a5a0dSRob Bradford use vm_memory::ByteValued; 10aa98589bSRob Bradford 11*88a9f799SRob Bradford use crate::MigratableError; 12*88a9f799SRob Bradford 13aa98589bSRob Bradford // Migration protocol 14aa98589bSRob Bradford // 1: Source establishes communication with destination (file socket or TCP connection.) 15aa98589bSRob Bradford // (The establishment is out of scope.) 16aa98589bSRob Bradford // 2: Source -> Dest : send "start command" 17aa98589bSRob Bradford // 3: Dest -> Source : sends "ok response" when read to accept state data 1811a69450SRob Bradford // 4: Source -> Dest : sends "config command" followed by config data, length 1911a69450SRob Bradford // in command is length of config data 20aa98589bSRob Bradford // 5: Dest -> Source : sends "ok response" when ready to accept memory data 21aa98589bSRob Bradford // 6: Source -> Dest : send "memory command" followed by table of u64 pairs (GPA, size) 22aa98589bSRob Bradford // followed by the memory described in those pairs. 23aa98589bSRob Bradford // !! length is size of table i.e. 16 * number of ranges !! 24aa98589bSRob Bradford // 7: Dest -> Source : sends "ok response" when ready to accept more memory data 2511a69450SRob Bradford // 8..(n-4): Repeat steps 6 and 7 until source has no more memory to send 2611a69450SRob Bradford // (n-3): Source -> Dest : sends "state command" followed by state data, length 2711a69450SRob Bradford // in command is length of config data 2811a69450SRob Bradford // (n-2): Dest -> Source : sends "ok response" 29aa98589bSRob Bradford // (n-1): Source -> Dest : send "complete command" 30aa98589bSRob Bradford // n: Dest -> Source: sends "ok response" 3133fd0af8SRob Bradford // 3233fd0af8SRob Bradford // "Local version": (Handing FDs across socket for memory) 3333fd0af8SRob Bradford // 1: Source establishes communication with destination (file socket or TCP connection.) 3433fd0af8SRob Bradford // (The establishment is out of scope.) 3533fd0af8SRob Bradford // 2: Source -> Dest : send "start command" 3633fd0af8SRob Bradford // 3: Dest -> Source : sends "ok response" when read to accept state data 3733fd0af8SRob Bradford // 4: Source -> Dest : sends "config command" followed by config data, length 3833fd0af8SRob Bradford // in command is length of config data 3933fd0af8SRob Bradford // 5: Dest -> Source : sends "ok response" when ready to accept memory data 4033fd0af8SRob Bradford // 6: Source -> Dest : send "memory fd command" followed by u16 slot ID and FD for memory 4133fd0af8SRob Bradford // 7: Dest -> Source : sends "ok response" when received 4233fd0af8SRob Bradford // 8..(n-4): Repeat steps 6 and 7 until source has no more memory to send 4333fd0af8SRob Bradford // (n-3): Source -> Dest : sends "state command" followed by state data, length 4433fd0af8SRob Bradford // in command is length of config data 4533fd0af8SRob Bradford // (n-2): Dest -> Source : sends "ok response" 4633fd0af8SRob Bradford // (n-1): Source -> Dest : send "complete command" 4733fd0af8SRob Bradford // n: Dest -> Source: sends "ok response" 4833fd0af8SRob Bradford // 49aa98589bSRob Bradford // The destination can at any time send an "error response" to cancel 50aa98589bSRob Bradford // The source can at any time send an "abandon request" to cancel 51aa98589bSRob Bradford 52aa98589bSRob Bradford #[repr(u16)] 53aa98589bSRob Bradford #[derive(Copy, Clone)] 54aa98589bSRob Bradford pub enum Command { 55aa98589bSRob Bradford Invalid, 56aa98589bSRob Bradford Start, 5711a69450SRob Bradford Config, 58aa98589bSRob Bradford State, 59aa98589bSRob Bradford Memory, 60aa98589bSRob Bradford Complete, 61aa98589bSRob Bradford Abandon, 62735658a4SRob Bradford MemoryFd, 63aa98589bSRob Bradford } 64aa98589bSRob Bradford 65aa98589bSRob Bradford impl Default for Command { default() -> Self66aa98589bSRob Bradford fn default() -> Self { 67aa98589bSRob Bradford Self::Invalid 68aa98589bSRob Bradford } 69aa98589bSRob Bradford } 70aa98589bSRob Bradford 71aa98589bSRob Bradford #[repr(C)] 728e9a5a0dSRob Bradford #[derive(Default, Copy, Clone)] 73aa98589bSRob Bradford pub struct Request { 74aa98589bSRob Bradford command: Command, 75aa98589bSRob Bradford padding: [u8; 6], 76aa98589bSRob Bradford length: u64, // Length of payload for command excluding the Request struct 77aa98589bSRob Bradford } 78aa98589bSRob Bradford 791a2b0188SWei Liu // SAFETY: Request contains a series of integers with no implicit padding 801a2b0188SWei Liu unsafe impl ByteValued for Request {} 811a2b0188SWei Liu 82aa98589bSRob Bradford impl Request { new(command: Command, length: u64) -> Self83aa98589bSRob Bradford pub fn new(command: Command, length: u64) -> Self { 84aa98589bSRob Bradford Self { 85aa98589bSRob Bradford command, 86aa98589bSRob Bradford length, 87aa98589bSRob Bradford ..Default::default() 88aa98589bSRob Bradford } 89aa98589bSRob Bradford } 90aa98589bSRob Bradford start() -> Self91aa98589bSRob Bradford pub fn start() -> Self { 92aa98589bSRob Bradford Self::new(Command::Start, 0) 93aa98589bSRob Bradford } 94aa98589bSRob Bradford state(length: u64) -> Self95aa98589bSRob Bradford pub fn state(length: u64) -> Self { 96aa98589bSRob Bradford Self::new(Command::State, length) 97aa98589bSRob Bradford } 98aa98589bSRob Bradford config(length: u64) -> Self9911a69450SRob Bradford pub fn config(length: u64) -> Self { 10011a69450SRob Bradford Self::new(Command::Config, length) 10111a69450SRob Bradford } 10211a69450SRob Bradford memory(length: u64) -> Self103aa98589bSRob Bradford pub fn memory(length: u64) -> Self { 104aa98589bSRob Bradford Self::new(Command::Memory, length) 105aa98589bSRob Bradford } 106aa98589bSRob Bradford memory_fd(length: u64) -> Self107735658a4SRob Bradford pub fn memory_fd(length: u64) -> Self { 108735658a4SRob Bradford Self::new(Command::MemoryFd, length) 109735658a4SRob Bradford } 110735658a4SRob Bradford complete() -> Self111aa98589bSRob Bradford pub fn complete() -> Self { 112aa98589bSRob Bradford Self::new(Command::Complete, 0) 113aa98589bSRob Bradford } 114aa98589bSRob Bradford abandon() -> Self115aa98589bSRob Bradford pub fn abandon() -> Self { 116aa98589bSRob Bradford Self::new(Command::Abandon, 0) 117aa98589bSRob Bradford } 118aa98589bSRob Bradford command(&self) -> Command119aa98589bSRob Bradford pub fn command(&self) -> Command { 120aa98589bSRob Bradford self.command 121aa98589bSRob Bradford } 122aa98589bSRob Bradford length(&self) -> u64123aa98589bSRob Bradford pub fn length(&self) -> u64 { 124aa98589bSRob Bradford self.length 125aa98589bSRob Bradford } 126aa98589bSRob Bradford read_from(fd: &mut dyn Read) -> Result<Request, MigratableError>127aa98589bSRob Bradford pub fn read_from(fd: &mut dyn Read) -> Result<Request, MigratableError> { 128aa98589bSRob Bradford let mut request = Request::default(); 1298e9a5a0dSRob Bradford fd.read_exact(Self::as_mut_slice(&mut request)) 130aa98589bSRob Bradford .map_err(MigratableError::MigrateSocket)?; 131aa98589bSRob Bradford 132aa98589bSRob Bradford Ok(request) 133aa98589bSRob Bradford } 134aa98589bSRob Bradford write_to(&self, fd: &mut dyn Write) -> Result<(), MigratableError>135aa98589bSRob Bradford pub fn write_to(&self, fd: &mut dyn Write) -> Result<(), MigratableError> { 1368e9a5a0dSRob Bradford fd.write_all(Self::as_slice(self)) 137aa98589bSRob Bradford .map_err(MigratableError::MigrateSocket) 138aa98589bSRob Bradford } 139aa98589bSRob Bradford } 140aa98589bSRob Bradford 141aa98589bSRob Bradford #[repr(u16)] 1422716bc33SRob Bradford #[derive(Copy, Clone, PartialEq, Eq)] 143aa98589bSRob Bradford pub enum Status { 144aa98589bSRob Bradford Invalid, 145aa98589bSRob Bradford Ok, 146aa98589bSRob Bradford Error, 147aa98589bSRob Bradford } 148aa98589bSRob Bradford 149aa98589bSRob Bradford impl Default for Status { default() -> Self150aa98589bSRob Bradford fn default() -> Self { 151aa98589bSRob Bradford Self::Invalid 152aa98589bSRob Bradford } 153aa98589bSRob Bradford } 154aa98589bSRob Bradford 155aa98589bSRob Bradford #[repr(C)] 1568e9a5a0dSRob Bradford #[derive(Default, Copy, Clone)] 157aa98589bSRob Bradford pub struct Response { 158aa98589bSRob Bradford status: Status, 159aa98589bSRob Bradford padding: [u8; 6], 160aa98589bSRob Bradford length: u64, // Length of payload for command excluding the Response struct 161aa98589bSRob Bradford } 162aa98589bSRob Bradford 1631a2b0188SWei Liu // SAFETY: Response contains a series of integers with no implicit padding 1641a2b0188SWei Liu unsafe impl ByteValued for Response {} 1651a2b0188SWei Liu 166aa98589bSRob Bradford impl Response { new(status: Status, length: u64) -> Self167aa98589bSRob Bradford pub fn new(status: Status, length: u64) -> Self { 168aa98589bSRob Bradford Self { 169aa98589bSRob Bradford status, 170aa98589bSRob Bradford length, 171aa98589bSRob Bradford ..Default::default() 172aa98589bSRob Bradford } 173aa98589bSRob Bradford } 174aa98589bSRob Bradford ok() -> Self175aa98589bSRob Bradford pub fn ok() -> Self { 176aa98589bSRob Bradford Self::new(Status::Ok, 0) 177aa98589bSRob Bradford } 178aa98589bSRob Bradford error() -> Self179aa98589bSRob Bradford pub fn error() -> Self { 180aa98589bSRob Bradford Self::new(Status::Error, 0) 181aa98589bSRob Bradford } 182aa98589bSRob Bradford status(&self) -> Status183aa98589bSRob Bradford pub fn status(&self) -> Status { 184aa98589bSRob Bradford self.status 185aa98589bSRob Bradford } 186aa98589bSRob Bradford read_from(fd: &mut dyn Read) -> Result<Response, MigratableError>187aa98589bSRob Bradford pub fn read_from(fd: &mut dyn Read) -> Result<Response, MigratableError> { 188aa98589bSRob Bradford let mut response = Response::default(); 1898e9a5a0dSRob Bradford fd.read_exact(Self::as_mut_slice(&mut response)) 190aa98589bSRob Bradford .map_err(MigratableError::MigrateSocket)?; 191aa98589bSRob Bradford 192aa98589bSRob Bradford Ok(response) 193aa98589bSRob Bradford } 194aa98589bSRob Bradford ok_or_abandon<T>( self, fd: &mut T, error: MigratableError, ) -> Result<Response, MigratableError> where T: Read + Write,195e97cee99SRob Bradford pub fn ok_or_abandon<T>( 196e97cee99SRob Bradford self, 197e97cee99SRob Bradford fd: &mut T, 198e97cee99SRob Bradford error: MigratableError, 199e97cee99SRob Bradford ) -> Result<Response, MigratableError> 200e97cee99SRob Bradford where 201e97cee99SRob Bradford T: Read + Write, 202e97cee99SRob Bradford { 203e97cee99SRob Bradford if self.status != Status::Ok { 204e97cee99SRob Bradford Request::abandon().write_to(fd)?; 205e97cee99SRob Bradford Response::read_from(fd)?; 206e97cee99SRob Bradford return Err(error); 207e97cee99SRob Bradford } 208e97cee99SRob Bradford Ok(self) 209e97cee99SRob Bradford } 210e97cee99SRob Bradford write_to(&self, fd: &mut dyn Write) -> Result<(), MigratableError>211aa98589bSRob Bradford pub fn write_to(&self, fd: &mut dyn Write) -> Result<(), MigratableError> { 2128e9a5a0dSRob Bradford fd.write_all(Self::as_slice(self)) 213aa98589bSRob Bradford .map_err(MigratableError::MigrateSocket) 214aa98589bSRob Bradford } 215aa98589bSRob Bradford } 216aa98589bSRob Bradford 217aa98589bSRob Bradford #[repr(C)] 21810ab87d6SRob Bradford #[derive(Clone, Default, Serialize, Deserialize)] 219aa98589bSRob Bradford pub struct MemoryRange { 220aa98589bSRob Bradford pub gpa: u64, 221aa98589bSRob Bradford pub length: u64, 222aa98589bSRob Bradford } 223aa98589bSRob Bradford 22410ab87d6SRob Bradford #[derive(Clone, Default, Serialize, Deserialize)] 225aa98589bSRob Bradford pub struct MemoryRangeTable { 226aa98589bSRob Bradford data: Vec<MemoryRange>, 227aa98589bSRob Bradford } 228aa98589bSRob Bradford 229aa98589bSRob Bradford impl MemoryRangeTable { from_bitmap(bitmap: Vec<u64>, start_addr: u64, page_size: u64) -> Self230a1caa654SSebastien Boeuf pub fn from_bitmap(bitmap: Vec<u64>, start_addr: u64, page_size: u64) -> Self { 23179425b6aSSebastien Boeuf let mut table = MemoryRangeTable::default(); 23279425b6aSSebastien Boeuf let mut entry: Option<MemoryRange> = None; 23379425b6aSSebastien Boeuf for (i, block) in bitmap.iter().enumerate() { 23479425b6aSSebastien Boeuf for j in 0..64 { 23579425b6aSSebastien Boeuf let is_page_dirty = ((block >> j) & 1u64) != 0u64; 23679425b6aSSebastien Boeuf let page_offset = ((i * 64) + j) as u64 * page_size; 23779425b6aSSebastien Boeuf if is_page_dirty { 23879425b6aSSebastien Boeuf if let Some(entry) = &mut entry { 23979425b6aSSebastien Boeuf entry.length += page_size; 24079425b6aSSebastien Boeuf } else { 24179425b6aSSebastien Boeuf entry = Some(MemoryRange { 24279425b6aSSebastien Boeuf gpa: start_addr + page_offset, 24379425b6aSSebastien Boeuf length: page_size, 24479425b6aSSebastien Boeuf }); 24579425b6aSSebastien Boeuf } 24679425b6aSSebastien Boeuf } else if let Some(entry) = entry.take() { 24779425b6aSSebastien Boeuf table.push(entry); 24879425b6aSSebastien Boeuf } 24979425b6aSSebastien Boeuf } 25079425b6aSSebastien Boeuf } 25179425b6aSSebastien Boeuf if let Some(entry) = entry.take() { 25279425b6aSSebastien Boeuf table.push(entry); 25379425b6aSSebastien Boeuf } 25479425b6aSSebastien Boeuf 25579425b6aSSebastien Boeuf table 25679425b6aSSebastien Boeuf } 25779425b6aSSebastien Boeuf regions(&self) -> &[MemoryRange]258aa98589bSRob Bradford pub fn regions(&self) -> &[MemoryRange] { 259aa98589bSRob Bradford &self.data 260aa98589bSRob Bradford } 261aa98589bSRob Bradford push(&mut self, range: MemoryRange)262aa98589bSRob Bradford pub fn push(&mut self, range: MemoryRange) { 263aa98589bSRob Bradford self.data.push(range) 264aa98589bSRob Bradford } 265aa98589bSRob Bradford read_from(fd: &mut dyn Read, length: u64) -> Result<MemoryRangeTable, MigratableError>266aa98589bSRob Bradford pub fn read_from(fd: &mut dyn Read, length: u64) -> Result<MemoryRangeTable, MigratableError> { 267aa98589bSRob Bradford assert!(length as usize % std::mem::size_of::<MemoryRange>() == 0); 268aa98589bSRob Bradford 269c8e3c1eeSSebastien Boeuf let mut data: Vec<MemoryRange> = Vec::new(); 270c8e3c1eeSSebastien Boeuf data.resize_with( 271c8e3c1eeSSebastien Boeuf length as usize / (std::mem::size_of::<MemoryRange>()), 272c8e3c1eeSSebastien Boeuf Default::default, 273c8e3c1eeSSebastien Boeuf ); 2747bf0cc1eSPhilipp Schuster // SAFETY: the slice is constructed with the correct arguments 275aa98589bSRob Bradford fd.read_exact(unsafe { 276aa98589bSRob Bradford std::slice::from_raw_parts_mut( 277aa98589bSRob Bradford data.as_ptr() as *mut MemoryRange as *mut u8, 278aa98589bSRob Bradford length as usize, 279aa98589bSRob Bradford ) 280aa98589bSRob Bradford }) 281aa98589bSRob Bradford .map_err(MigratableError::MigrateSocket)?; 282aa98589bSRob Bradford 283aa98589bSRob Bradford Ok(Self { data }) 284aa98589bSRob Bradford } 285aa98589bSRob Bradford length(&self) -> u64286aa98589bSRob Bradford pub fn length(&self) -> u64 { 287aa98589bSRob Bradford (std::mem::size_of::<MemoryRange>() * self.data.len()) as u64 288aa98589bSRob Bradford } 289aa98589bSRob Bradford write_to(&self, fd: &mut dyn Write) -> Result<(), MigratableError>290aa98589bSRob Bradford pub fn write_to(&self, fd: &mut dyn Write) -> Result<(), MigratableError> { 2917bf0cc1eSPhilipp Schuster // SAFETY: the slice is constructed with the correct arguments 292aa98589bSRob Bradford fd.write_all(unsafe { 293aac614e2SYu Li std::slice::from_raw_parts(self.data.as_ptr() as *const u8, self.length() as usize) 294aa98589bSRob Bradford }) 295aa98589bSRob Bradford .map_err(MigratableError::MigrateSocket) 296aa98589bSRob Bradford } 29779425b6aSSebastien Boeuf is_empty(&self) -> bool29879425b6aSSebastien Boeuf pub fn is_empty(&self) -> bool { 29979425b6aSSebastien Boeuf self.data.is_empty() 30079425b6aSSebastien Boeuf } 30179425b6aSSebastien Boeuf extend(&mut self, table: Self)30279425b6aSSebastien Boeuf pub fn extend(&mut self, table: Self) { 30379425b6aSSebastien Boeuf self.data.extend(table.data) 30479425b6aSSebastien Boeuf } 30579425b6aSSebastien Boeuf new_from_tables(tables: Vec<Self>) -> Self30679425b6aSSebastien Boeuf pub fn new_from_tables(tables: Vec<Self>) -> Self { 30779425b6aSSebastien Boeuf let mut data = Vec::new(); 30879425b6aSSebastien Boeuf for table in tables { 30979425b6aSSebastien Boeuf data.extend(table.data); 31079425b6aSSebastien Boeuf } 31179425b6aSSebastien Boeuf Self { data } 31279425b6aSSebastien Boeuf } 313aa98589bSRob Bradford } 314