1 // Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 // SPDX-License-Identifier: Apache-2.0 3 // 4 // Portions Copyright 2017 The Chromium OS Authors. All rights reserved. 5 // Use of this source code is governed by a BSD-style license that can be 6 // found in the LICENSE-BSD-3-Clause file. 7 8 use std::collections::VecDeque; 9 use std::sync::{Arc, Barrier}; 10 use std::{io, result}; 11 use versionize::{VersionMap, Versionize, VersionizeResult}; 12 use versionize_derive::Versionize; 13 use vm_device::interrupt::InterruptSourceGroup; 14 use vm_device::BusDevice; 15 use vm_migration::{ 16 Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable, VersionMapped, 17 }; 18 use vmm_sys_util::errno::Result; 19 20 const LOOP_SIZE: usize = 0x40; 21 22 const DATA: u8 = 0; 23 const IER: u8 = 1; 24 const IIR: u8 = 2; 25 const LCR: u8 = 3; 26 const MCR: u8 = 4; 27 const LSR: u8 = 5; 28 const MSR: u8 = 6; 29 const SCR: u8 = 7; 30 31 const DLAB_LOW: u8 = 0; 32 const DLAB_HIGH: u8 = 1; 33 34 const IER_RECV_BIT: u8 = 0x1; 35 const IER_THR_BIT: u8 = 0x2; 36 const IER_FIFO_BITS: u8 = 0x0f; 37 38 const IIR_FIFO_BITS: u8 = 0xc0; 39 const IIR_NONE_BIT: u8 = 0x1; 40 const IIR_THR_BIT: u8 = 0x2; 41 const IIR_RECV_BIT: u8 = 0x4; 42 43 const LCR_DLAB_BIT: u8 = 0x80; 44 45 const LSR_DATA_BIT: u8 = 0x1; 46 const LSR_EMPTY_BIT: u8 = 0x20; 47 const LSR_IDLE_BIT: u8 = 0x40; 48 49 const MCR_LOOP_BIT: u8 = 0x10; 50 51 const DEFAULT_INTERRUPT_IDENTIFICATION: u8 = IIR_NONE_BIT; // no pending interrupt 52 const DEFAULT_LINE_STATUS: u8 = LSR_EMPTY_BIT | LSR_IDLE_BIT; // THR empty and line is idle 53 const DEFAULT_LINE_CONTROL: u8 = 0x3; // 8-bits per character 54 const DEFAULT_MODEM_CONTROL: u8 = 0x8; // Auxiliary output 2 55 const DEFAULT_MODEM_STATUS: u8 = 0x20 | 0x10 | 0x80; // data ready, clear to send, carrier detect 56 const DEFAULT_BAUD_DIVISOR: u16 = 12; // 9600 bps 57 58 /// Emulates serial COM ports commonly seen on x86 I/O ports 0x3f8/0x2f8/0x3e8/0x2e8. 59 /// 60 /// This can optionally write the guest's output to a Write trait object. To send input to the 61 /// guest, use `queue_input_bytes`. 62 pub struct Serial { 63 id: String, 64 interrupt_enable: u8, 65 interrupt_identification: u8, 66 interrupt: Arc<dyn InterruptSourceGroup>, 67 line_control: u8, 68 line_status: u8, 69 modem_control: u8, 70 modem_status: u8, 71 scratch: u8, 72 baud_divisor: u16, 73 in_buffer: VecDeque<u8>, 74 out: Option<Box<dyn io::Write + Send>>, 75 } 76 77 #[derive(Versionize)] 78 pub struct SerialState { 79 interrupt_enable: u8, 80 interrupt_identification: u8, 81 line_control: u8, 82 line_status: u8, 83 modem_control: u8, 84 modem_status: u8, 85 scratch: u8, 86 baud_divisor: u16, 87 in_buffer: Vec<u8>, 88 } 89 impl VersionMapped for SerialState {} 90 91 impl Serial { 92 pub fn new( 93 id: String, 94 interrupt: Arc<dyn InterruptSourceGroup>, 95 out: Option<Box<dyn io::Write + Send>>, 96 ) -> Serial { 97 Serial { 98 id, 99 interrupt_enable: 0, 100 interrupt_identification: DEFAULT_INTERRUPT_IDENTIFICATION, 101 interrupt, 102 line_control: DEFAULT_LINE_CONTROL, 103 line_status: DEFAULT_LINE_STATUS, 104 modem_control: DEFAULT_MODEM_CONTROL, 105 modem_status: DEFAULT_MODEM_STATUS, 106 scratch: 0, 107 baud_divisor: DEFAULT_BAUD_DIVISOR, 108 in_buffer: VecDeque::new(), 109 out, 110 } 111 } 112 113 /// Constructs a Serial port ready for output. 114 pub fn new_out( 115 id: String, 116 interrupt: Arc<dyn InterruptSourceGroup>, 117 out: Box<dyn io::Write + Send>, 118 ) -> Serial { 119 Self::new(id, interrupt, Some(out)) 120 } 121 122 /// Constructs a Serial port with no connected output. 123 pub fn new_sink(id: String, interrupt: Arc<dyn InterruptSourceGroup>) -> Serial { 124 Self::new(id, interrupt, None) 125 } 126 127 pub fn set_out(&mut self, out: Box<dyn io::Write + Send>) { 128 self.out = Some(out); 129 } 130 131 /// Queues raw bytes for the guest to read and signals the interrupt if the line status would 132 /// change. 133 pub fn queue_input_bytes(&mut self, c: &[u8]) -> Result<()> { 134 if !self.is_loop() { 135 self.in_buffer.extend(c); 136 self.recv_data()?; 137 } 138 Ok(()) 139 } 140 141 pub fn flush_output(&mut self) -> result::Result<(), io::Error> { 142 if let Some(out) = self.out.as_mut() { 143 out.flush()?; 144 } 145 Ok(()) 146 } 147 148 fn is_dlab_set(&self) -> bool { 149 (self.line_control & LCR_DLAB_BIT) != 0 150 } 151 152 fn is_recv_intr_enabled(&self) -> bool { 153 (self.interrupt_enable & IER_RECV_BIT) != 0 154 } 155 156 fn is_thr_intr_enabled(&self) -> bool { 157 (self.interrupt_enable & IER_THR_BIT) != 0 158 } 159 160 fn is_loop(&self) -> bool { 161 (self.modem_control & MCR_LOOP_BIT) != 0 162 } 163 164 fn add_intr_bit(&mut self, bit: u8) { 165 self.interrupt_identification &= !IIR_NONE_BIT; 166 self.interrupt_identification |= bit; 167 } 168 169 fn del_intr_bit(&mut self, bit: u8) { 170 self.interrupt_identification &= !bit; 171 if self.interrupt_identification == 0x0 { 172 self.interrupt_identification = IIR_NONE_BIT; 173 } 174 } 175 176 fn thr_empty(&mut self) -> Result<()> { 177 if self.is_thr_intr_enabled() { 178 self.add_intr_bit(IIR_THR_BIT); 179 self.trigger_interrupt()? 180 } 181 Ok(()) 182 } 183 184 fn recv_data(&mut self) -> Result<()> { 185 if self.is_recv_intr_enabled() { 186 self.add_intr_bit(IIR_RECV_BIT); 187 self.trigger_interrupt()? 188 } 189 self.line_status |= LSR_DATA_BIT; 190 Ok(()) 191 } 192 193 fn trigger_interrupt(&mut self) -> result::Result<(), io::Error> { 194 self.interrupt.trigger(0) 195 } 196 197 fn iir_reset(&mut self) { 198 self.interrupt_identification = DEFAULT_INTERRUPT_IDENTIFICATION; 199 } 200 201 fn handle_write(&mut self, offset: u8, v: u8) -> Result<()> { 202 match offset as u8 { 203 DLAB_LOW if self.is_dlab_set() => { 204 self.baud_divisor = (self.baud_divisor & 0xff00) | u16::from(v) 205 } 206 DLAB_HIGH if self.is_dlab_set() => { 207 self.baud_divisor = (self.baud_divisor & 0x00ff) | ((u16::from(v)) << 8) 208 } 209 DATA => { 210 if self.is_loop() { 211 if self.in_buffer.len() < LOOP_SIZE { 212 self.in_buffer.push_back(v); 213 self.recv_data()?; 214 } 215 } else { 216 if let Some(out) = self.out.as_mut() { 217 out.write_all(&[v])?; 218 out.flush()?; 219 } 220 self.thr_empty()?; 221 } 222 } 223 IER => self.interrupt_enable = v & IER_FIFO_BITS, 224 LCR => self.line_control = v, 225 MCR => self.modem_control = v, 226 SCR => self.scratch = v, 227 _ => {} 228 } 229 Ok(()) 230 } 231 232 fn state(&self) -> SerialState { 233 SerialState { 234 interrupt_enable: self.interrupt_enable, 235 interrupt_identification: self.interrupt_identification, 236 line_control: self.line_control, 237 line_status: self.line_status, 238 modem_control: self.modem_control, 239 modem_status: self.modem_status, 240 scratch: self.scratch, 241 baud_divisor: self.baud_divisor, 242 in_buffer: self.in_buffer.clone().into(), 243 } 244 } 245 246 fn set_state(&mut self, state: &SerialState) { 247 self.interrupt_enable = state.interrupt_enable; 248 self.interrupt_identification = state.interrupt_identification; 249 self.line_control = state.line_control; 250 self.line_status = state.line_status; 251 self.modem_control = state.modem_control; 252 self.modem_status = state.modem_status; 253 self.scratch = state.scratch; 254 self.baud_divisor = state.baud_divisor; 255 self.in_buffer = state.in_buffer.clone().into(); 256 } 257 } 258 259 impl BusDevice for Serial { 260 fn read(&mut self, _base: u64, offset: u64, data: &mut [u8]) { 261 if data.len() != 1 { 262 return; 263 } 264 265 data[0] = match offset as u8 { 266 DLAB_LOW if self.is_dlab_set() => self.baud_divisor as u8, 267 DLAB_HIGH if self.is_dlab_set() => (self.baud_divisor >> 8) as u8, 268 DATA => { 269 self.del_intr_bit(IIR_RECV_BIT); 270 if self.in_buffer.len() <= 1 { 271 self.line_status &= !LSR_DATA_BIT; 272 } 273 self.in_buffer.pop_front().unwrap_or_default() 274 } 275 IER => self.interrupt_enable, 276 IIR => { 277 let v = self.interrupt_identification | IIR_FIFO_BITS; 278 self.iir_reset(); 279 v 280 } 281 LCR => self.line_control, 282 MCR => self.modem_control, 283 LSR => self.line_status, 284 MSR => self.modem_status, 285 SCR => self.scratch, 286 _ => 0, 287 }; 288 } 289 290 fn write(&mut self, _base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> { 291 if data.len() != 1 { 292 return None; 293 } 294 295 self.handle_write(offset as u8, data[0]).ok(); 296 297 None 298 } 299 } 300 301 impl Snapshottable for Serial { 302 fn id(&self) -> String { 303 self.id.clone() 304 } 305 306 fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> { 307 Snapshot::new_from_versioned_state(&self.id, &self.state()) 308 } 309 310 fn restore(&mut self, snapshot: Snapshot) -> std::result::Result<(), MigratableError> { 311 self.set_state(&snapshot.to_versioned_state(&self.id)?); 312 Ok(()) 313 } 314 } 315 316 impl Pausable for Serial {} 317 impl Transportable for Serial {} 318 impl Migratable for Serial {} 319 320 #[cfg(test)] 321 mod tests { 322 use super::*; 323 use std::io; 324 use std::sync::{Arc, Mutex}; 325 use vm_device::interrupt::{InterruptIndex, InterruptSourceConfig}; 326 use vmm_sys_util::eventfd::EventFd; 327 328 const SERIAL_NAME: &str = "serial"; 329 330 struct TestInterrupt { 331 event_fd: EventFd, 332 } 333 334 impl InterruptSourceGroup for TestInterrupt { 335 fn trigger(&self, _index: InterruptIndex) -> result::Result<(), std::io::Error> { 336 self.event_fd.write(1) 337 } 338 fn update( 339 &self, 340 _index: InterruptIndex, 341 _config: InterruptSourceConfig, 342 _masked: bool, 343 ) -> result::Result<(), std::io::Error> { 344 Ok(()) 345 } 346 fn notifier(&self, _index: InterruptIndex) -> Option<EventFd> { 347 Some(self.event_fd.try_clone().unwrap()) 348 } 349 } 350 351 impl TestInterrupt { 352 fn new(event_fd: EventFd) -> Self { 353 TestInterrupt { event_fd } 354 } 355 } 356 357 #[derive(Clone)] 358 struct SharedBuffer { 359 buf: Arc<Mutex<Vec<u8>>>, 360 } 361 362 impl SharedBuffer { 363 fn new() -> SharedBuffer { 364 SharedBuffer { 365 buf: Arc::new(Mutex::new(Vec::new())), 366 } 367 } 368 } 369 370 impl io::Write for SharedBuffer { 371 fn write(&mut self, buf: &[u8]) -> io::Result<usize> { 372 self.buf.lock().unwrap().write(buf) 373 } 374 fn flush(&mut self) -> io::Result<()> { 375 self.buf.lock().unwrap().flush() 376 } 377 } 378 379 #[test] 380 fn serial_output() { 381 let intr_evt = EventFd::new(0).unwrap(); 382 let serial_out = SharedBuffer::new(); 383 let mut serial = Serial::new_out( 384 String::from(SERIAL_NAME), 385 Arc::new(TestInterrupt::new(intr_evt.try_clone().unwrap())), 386 Box::new(serial_out.clone()), 387 ); 388 389 serial.write(0, DATA as u64, &[b'x', b'y']); 390 serial.write(0, DATA as u64, &[b'a']); 391 serial.write(0, DATA as u64, &[b'b']); 392 serial.write(0, DATA as u64, &[b'c']); 393 assert_eq!( 394 serial_out.buf.lock().unwrap().as_slice(), 395 &[b'a', b'b', b'c'] 396 ); 397 } 398 399 #[test] 400 fn serial_input() { 401 let intr_evt = EventFd::new(0).unwrap(); 402 let serial_out = SharedBuffer::new(); 403 let mut serial = Serial::new_out( 404 String::from(SERIAL_NAME), 405 Arc::new(TestInterrupt::new(intr_evt.try_clone().unwrap())), 406 Box::new(serial_out), 407 ); 408 409 // write 1 to the interrupt event fd, so that read doesn't block in case the event fd 410 // counter doesn't change (for 0 it blocks) 411 assert!(intr_evt.write(1).is_ok()); 412 serial.write(0, IER as u64, &[IER_RECV_BIT]); 413 serial.queue_input_bytes(&[b'a', b'b', b'c']).unwrap(); 414 415 assert_eq!(intr_evt.read().unwrap(), 2); 416 417 // check if reading in a 2-length array doesn't have side effects 418 let mut data = [0u8, 0u8]; 419 serial.read(0, DATA as u64, &mut data[..]); 420 assert_eq!(data, [0u8, 0u8]); 421 422 let mut data = [0u8]; 423 serial.read(0, LSR as u64, &mut data[..]); 424 assert_ne!(data[0] & LSR_DATA_BIT, 0); 425 serial.read(0, DATA as u64, &mut data[..]); 426 assert_eq!(data[0], b'a'); 427 serial.read(0, DATA as u64, &mut data[..]); 428 assert_eq!(data[0], b'b'); 429 serial.read(0, DATA as u64, &mut data[..]); 430 assert_eq!(data[0], b'c'); 431 432 // check if reading from the largest u8 offset returns 0 433 serial.read(0, 0xff, &mut data[..]); 434 assert_eq!(data[0], 0); 435 } 436 437 #[test] 438 fn serial_thr() { 439 let intr_evt = EventFd::new(0).unwrap(); 440 let mut serial = Serial::new_sink( 441 String::from(SERIAL_NAME), 442 Arc::new(TestInterrupt::new(intr_evt.try_clone().unwrap())), 443 ); 444 445 // write 1 to the interrupt event fd, so that read doesn't block in case the event fd 446 // counter doesn't change (for 0 it blocks) 447 assert!(intr_evt.write(1).is_ok()); 448 serial.write(0, IER as u64, &[IER_THR_BIT]); 449 serial.write(0, DATA as u64, &[b'a']); 450 451 assert_eq!(intr_evt.read().unwrap(), 2); 452 let mut data = [0u8]; 453 serial.read(0, IER as u64, &mut data[..]); 454 assert_eq!(data[0] & IER_FIFO_BITS, IER_THR_BIT); 455 serial.read(0, IIR as u64, &mut data[..]); 456 assert_ne!(data[0] & IIR_THR_BIT, 0); 457 } 458 459 #[test] 460 fn serial_dlab() { 461 let intr_evt = EventFd::new(0).unwrap(); 462 let mut serial = Serial::new_sink( 463 String::from(SERIAL_NAME), 464 Arc::new(TestInterrupt::new(intr_evt.try_clone().unwrap())), 465 ); 466 467 serial.write(0, LCR as u64, &[LCR_DLAB_BIT]); 468 serial.write(0, DLAB_LOW as u64, &[0x12]); 469 serial.write(0, DLAB_HIGH as u64, &[0x34]); 470 471 let mut data = [0u8]; 472 serial.read(0, LCR as u64, &mut data[..]); 473 assert_eq!(data[0], LCR_DLAB_BIT); 474 serial.read(0, DLAB_LOW as u64, &mut data[..]); 475 assert_eq!(data[0], 0x12); 476 serial.read(0, DLAB_HIGH as u64, &mut data[..]); 477 assert_eq!(data[0], 0x34); 478 } 479 480 #[test] 481 fn serial_modem() { 482 let intr_evt = EventFd::new(0).unwrap(); 483 let mut serial = Serial::new_sink( 484 String::from(SERIAL_NAME), 485 Arc::new(TestInterrupt::new(intr_evt.try_clone().unwrap())), 486 ); 487 488 serial.write(0, MCR as u64, &[MCR_LOOP_BIT]); 489 serial.write(0, DATA as u64, &[b'a']); 490 serial.write(0, DATA as u64, &[b'b']); 491 serial.write(0, DATA as u64, &[b'c']); 492 493 let mut data = [0u8]; 494 serial.read(0, MSR as u64, &mut data[..]); 495 assert_eq!(data[0], DEFAULT_MODEM_STATUS); 496 serial.read(0, MCR as u64, &mut data[..]); 497 assert_eq!(data[0], MCR_LOOP_BIT); 498 serial.read(0, DATA as u64, &mut data[..]); 499 assert_eq!(data[0], b'a'); 500 serial.read(0, DATA as u64, &mut data[..]); 501 assert_eq!(data[0], b'b'); 502 serial.read(0, DATA as u64, &mut data[..]); 503 assert_eq!(data[0], b'c'); 504 } 505 506 #[test] 507 fn serial_scratch() { 508 let intr_evt = EventFd::new(0).unwrap(); 509 let mut serial = Serial::new_sink( 510 String::from(SERIAL_NAME), 511 Arc::new(TestInterrupt::new(intr_evt.try_clone().unwrap())), 512 ); 513 514 serial.write(0, SCR as u64, &[0x12]); 515 516 let mut data = [0u8]; 517 serial.read(0, SCR as u64, &mut data[..]); 518 assert_eq!(data[0], 0x12); 519 } 520 } 521