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 line_control: u8, 67 line_status: u8, 68 modem_control: u8, 69 modem_status: u8, 70 scratch: u8, 71 baud_divisor: u16, 72 in_buffer: VecDeque<u8>, 73 interrupt: Arc<dyn InterruptSourceGroup>, 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 state: Option<SerialState>, 97 ) -> Serial { 98 let ( 99 interrupt_enable, 100 interrupt_identification, 101 line_control, 102 line_status, 103 modem_control, 104 modem_status, 105 scratch, 106 baud_divisor, 107 in_buffer, 108 ) = if let Some(state) = state { 109 ( 110 state.interrupt_enable, 111 state.interrupt_identification, 112 state.line_control, 113 state.line_status, 114 state.modem_control, 115 state.modem_status, 116 state.scratch, 117 state.baud_divisor, 118 state.in_buffer.into(), 119 ) 120 } else { 121 ( 122 0, 123 DEFAULT_INTERRUPT_IDENTIFICATION, 124 DEFAULT_LINE_CONTROL, 125 DEFAULT_LINE_STATUS, 126 DEFAULT_MODEM_CONTROL, 127 DEFAULT_MODEM_STATUS, 128 0, 129 DEFAULT_BAUD_DIVISOR, 130 VecDeque::new(), 131 ) 132 }; 133 134 Serial { 135 id, 136 interrupt_enable, 137 interrupt_identification, 138 line_control, 139 line_status, 140 modem_control, 141 modem_status, 142 scratch, 143 baud_divisor, 144 in_buffer, 145 interrupt, 146 out, 147 } 148 } 149 150 /// Constructs a Serial port ready for output. 151 pub fn new_out( 152 id: String, 153 interrupt: Arc<dyn InterruptSourceGroup>, 154 out: Box<dyn io::Write + Send>, 155 state: Option<SerialState>, 156 ) -> Serial { 157 Self::new(id, interrupt, Some(out), state) 158 } 159 160 /// Constructs a Serial port with no connected output. 161 pub fn new_sink( 162 id: String, 163 interrupt: Arc<dyn InterruptSourceGroup>, 164 state: Option<SerialState>, 165 ) -> Serial { 166 Self::new(id, interrupt, None, state) 167 } 168 169 pub fn set_out(&mut self, out: Box<dyn io::Write + Send>) { 170 self.out = Some(out); 171 } 172 173 /// Queues raw bytes for the guest to read and signals the interrupt if the line status would 174 /// change. 175 pub fn queue_input_bytes(&mut self, c: &[u8]) -> Result<()> { 176 if !self.is_loop() { 177 self.in_buffer.extend(c); 178 self.recv_data()?; 179 } 180 Ok(()) 181 } 182 183 pub fn flush_output(&mut self) -> result::Result<(), io::Error> { 184 if let Some(out) = self.out.as_mut() { 185 out.flush()?; 186 } 187 Ok(()) 188 } 189 190 fn is_dlab_set(&self) -> bool { 191 (self.line_control & LCR_DLAB_BIT) != 0 192 } 193 194 fn is_recv_intr_enabled(&self) -> bool { 195 (self.interrupt_enable & IER_RECV_BIT) != 0 196 } 197 198 fn is_thr_intr_enabled(&self) -> bool { 199 (self.interrupt_enable & IER_THR_BIT) != 0 200 } 201 202 fn is_loop(&self) -> bool { 203 (self.modem_control & MCR_LOOP_BIT) != 0 204 } 205 206 fn add_intr_bit(&mut self, bit: u8) { 207 self.interrupt_identification &= !IIR_NONE_BIT; 208 self.interrupt_identification |= bit; 209 } 210 211 fn del_intr_bit(&mut self, bit: u8) { 212 self.interrupt_identification &= !bit; 213 if self.interrupt_identification == 0x0 { 214 self.interrupt_identification = IIR_NONE_BIT; 215 } 216 } 217 218 fn thr_empty(&mut self) -> Result<()> { 219 if self.is_thr_intr_enabled() { 220 self.add_intr_bit(IIR_THR_BIT); 221 self.trigger_interrupt()? 222 } 223 Ok(()) 224 } 225 226 fn recv_data(&mut self) -> Result<()> { 227 if self.is_recv_intr_enabled() { 228 self.add_intr_bit(IIR_RECV_BIT); 229 self.trigger_interrupt()? 230 } 231 self.line_status |= LSR_DATA_BIT; 232 Ok(()) 233 } 234 235 fn trigger_interrupt(&mut self) -> result::Result<(), io::Error> { 236 self.interrupt.trigger(0) 237 } 238 239 fn iir_reset(&mut self) { 240 self.interrupt_identification = DEFAULT_INTERRUPT_IDENTIFICATION; 241 } 242 243 fn handle_write(&mut self, offset: u8, v: u8) -> Result<()> { 244 match offset { 245 DLAB_LOW if self.is_dlab_set() => { 246 self.baud_divisor = (self.baud_divisor & 0xff00) | u16::from(v) 247 } 248 DLAB_HIGH if self.is_dlab_set() => { 249 self.baud_divisor = (self.baud_divisor & 0x00ff) | ((u16::from(v)) << 8) 250 } 251 DATA => { 252 if self.is_loop() { 253 if self.in_buffer.len() < LOOP_SIZE { 254 self.in_buffer.push_back(v); 255 self.recv_data()?; 256 } 257 } else { 258 if let Some(out) = self.out.as_mut() { 259 out.write_all(&[v])?; 260 out.flush()?; 261 } 262 self.thr_empty()?; 263 } 264 } 265 IER => self.interrupt_enable = v & IER_FIFO_BITS, 266 LCR => self.line_control = v, 267 MCR => self.modem_control = v, 268 SCR => self.scratch = v, 269 _ => {} 270 } 271 Ok(()) 272 } 273 274 fn state(&self) -> SerialState { 275 SerialState { 276 interrupt_enable: self.interrupt_enable, 277 interrupt_identification: self.interrupt_identification, 278 line_control: self.line_control, 279 line_status: self.line_status, 280 modem_control: self.modem_control, 281 modem_status: self.modem_status, 282 scratch: self.scratch, 283 baud_divisor: self.baud_divisor, 284 in_buffer: self.in_buffer.clone().into(), 285 } 286 } 287 } 288 289 impl BusDevice for Serial { 290 fn read(&mut self, _base: u64, offset: u64, data: &mut [u8]) { 291 if data.len() != 1 { 292 return; 293 } 294 295 data[0] = match offset as u8 { 296 DLAB_LOW if self.is_dlab_set() => self.baud_divisor as u8, 297 DLAB_HIGH if self.is_dlab_set() => (self.baud_divisor >> 8) as u8, 298 DATA => { 299 self.del_intr_bit(IIR_RECV_BIT); 300 if self.in_buffer.len() <= 1 { 301 self.line_status &= !LSR_DATA_BIT; 302 } 303 self.in_buffer.pop_front().unwrap_or_default() 304 } 305 IER => self.interrupt_enable, 306 IIR => { 307 let v = self.interrupt_identification | IIR_FIFO_BITS; 308 self.iir_reset(); 309 v 310 } 311 LCR => self.line_control, 312 MCR => self.modem_control, 313 LSR => self.line_status, 314 MSR => self.modem_status, 315 SCR => self.scratch, 316 _ => 0, 317 }; 318 } 319 320 fn write(&mut self, _base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> { 321 if data.len() != 1 { 322 return None; 323 } 324 325 self.handle_write(offset as u8, data[0]).ok(); 326 327 None 328 } 329 } 330 331 impl Snapshottable for Serial { 332 fn id(&self) -> String { 333 self.id.clone() 334 } 335 336 fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> { 337 Snapshot::new_from_versioned_state(&self.state()) 338 } 339 } 340 341 impl Pausable for Serial {} 342 impl Transportable for Serial {} 343 impl Migratable for Serial {} 344 345 #[cfg(test)] 346 mod tests { 347 use super::*; 348 use std::io; 349 use std::sync::{Arc, Mutex}; 350 use vm_device::interrupt::{InterruptIndex, InterruptSourceConfig}; 351 use vmm_sys_util::eventfd::EventFd; 352 353 const SERIAL_NAME: &str = "serial"; 354 355 struct TestInterrupt { 356 event_fd: EventFd, 357 } 358 359 impl InterruptSourceGroup for TestInterrupt { 360 fn trigger(&self, _index: InterruptIndex) -> result::Result<(), std::io::Error> { 361 self.event_fd.write(1) 362 } 363 fn update( 364 &self, 365 _index: InterruptIndex, 366 _config: InterruptSourceConfig, 367 _masked: bool, 368 _set_gsi: bool, 369 ) -> result::Result<(), std::io::Error> { 370 Ok(()) 371 } 372 fn set_gsi(&self) -> result::Result<(), std::io::Error> { 373 Ok(()) 374 } 375 fn notifier(&self, _index: InterruptIndex) -> Option<EventFd> { 376 Some(self.event_fd.try_clone().unwrap()) 377 } 378 } 379 380 impl TestInterrupt { 381 fn new(event_fd: EventFd) -> Self { 382 TestInterrupt { event_fd } 383 } 384 } 385 386 #[derive(Clone)] 387 struct SharedBuffer { 388 buf: Arc<Mutex<Vec<u8>>>, 389 } 390 391 impl SharedBuffer { 392 fn new() -> SharedBuffer { 393 SharedBuffer { 394 buf: Arc::new(Mutex::new(Vec::new())), 395 } 396 } 397 } 398 399 impl io::Write for SharedBuffer { 400 fn write(&mut self, buf: &[u8]) -> io::Result<usize> { 401 self.buf.lock().unwrap().write(buf) 402 } 403 fn flush(&mut self) -> io::Result<()> { 404 self.buf.lock().unwrap().flush() 405 } 406 } 407 408 #[test] 409 fn serial_output() { 410 let intr_evt = EventFd::new(0).unwrap(); 411 let serial_out = SharedBuffer::new(); 412 let mut serial = Serial::new_out( 413 String::from(SERIAL_NAME), 414 Arc::new(TestInterrupt::new(intr_evt.try_clone().unwrap())), 415 Box::new(serial_out.clone()), 416 None, 417 ); 418 419 serial.write(0, DATA as u64, &[b'x', b'y']); 420 serial.write(0, DATA as u64, &[b'a']); 421 serial.write(0, DATA as u64, &[b'b']); 422 serial.write(0, DATA as u64, &[b'c']); 423 assert_eq!( 424 serial_out.buf.lock().unwrap().as_slice(), 425 &[b'a', b'b', b'c'] 426 ); 427 } 428 429 #[test] 430 fn serial_input() { 431 let intr_evt = EventFd::new(0).unwrap(); 432 let serial_out = SharedBuffer::new(); 433 let mut serial = Serial::new_out( 434 String::from(SERIAL_NAME), 435 Arc::new(TestInterrupt::new(intr_evt.try_clone().unwrap())), 436 Box::new(serial_out), 437 None, 438 ); 439 440 // write 1 to the interrupt event fd, so that read doesn't block in case the event fd 441 // counter doesn't change (for 0 it blocks) 442 assert!(intr_evt.write(1).is_ok()); 443 serial.write(0, IER as u64, &[IER_RECV_BIT]); 444 serial.queue_input_bytes(&[b'a', b'b', b'c']).unwrap(); 445 446 assert_eq!(intr_evt.read().unwrap(), 2); 447 448 // check if reading in a 2-length array doesn't have side effects 449 let mut data = [0u8, 0u8]; 450 serial.read(0, DATA as u64, &mut data[..]); 451 assert_eq!(data, [0u8, 0u8]); 452 453 let mut data = [0u8]; 454 serial.read(0, LSR as u64, &mut data[..]); 455 assert_ne!(data[0] & LSR_DATA_BIT, 0); 456 serial.read(0, DATA as u64, &mut data[..]); 457 assert_eq!(data[0], b'a'); 458 serial.read(0, DATA as u64, &mut data[..]); 459 assert_eq!(data[0], b'b'); 460 serial.read(0, DATA as u64, &mut data[..]); 461 assert_eq!(data[0], b'c'); 462 463 // check if reading from the largest u8 offset returns 0 464 serial.read(0, 0xff, &mut data[..]); 465 assert_eq!(data[0], 0); 466 } 467 468 #[test] 469 fn serial_thr() { 470 let intr_evt = EventFd::new(0).unwrap(); 471 let mut serial = Serial::new_sink( 472 String::from(SERIAL_NAME), 473 Arc::new(TestInterrupt::new(intr_evt.try_clone().unwrap())), 474 None, 475 ); 476 477 // write 1 to the interrupt event fd, so that read doesn't block in case the event fd 478 // counter doesn't change (for 0 it blocks) 479 assert!(intr_evt.write(1).is_ok()); 480 serial.write(0, IER as u64, &[IER_THR_BIT]); 481 serial.write(0, DATA as u64, &[b'a']); 482 483 assert_eq!(intr_evt.read().unwrap(), 2); 484 let mut data = [0u8]; 485 serial.read(0, IER as u64, &mut data[..]); 486 assert_eq!(data[0] & IER_FIFO_BITS, IER_THR_BIT); 487 serial.read(0, IIR as u64, &mut data[..]); 488 assert_ne!(data[0] & IIR_THR_BIT, 0); 489 } 490 491 #[test] 492 fn serial_dlab() { 493 let intr_evt = EventFd::new(0).unwrap(); 494 let mut serial = Serial::new_sink( 495 String::from(SERIAL_NAME), 496 Arc::new(TestInterrupt::new(intr_evt.try_clone().unwrap())), 497 None, 498 ); 499 500 serial.write(0, LCR as u64, &[LCR_DLAB_BIT]); 501 serial.write(0, DLAB_LOW as u64, &[0x12]); 502 serial.write(0, DLAB_HIGH as u64, &[0x34]); 503 504 let mut data = [0u8]; 505 serial.read(0, LCR as u64, &mut data[..]); 506 assert_eq!(data[0], LCR_DLAB_BIT); 507 serial.read(0, DLAB_LOW as u64, &mut data[..]); 508 assert_eq!(data[0], 0x12); 509 serial.read(0, DLAB_HIGH as u64, &mut data[..]); 510 assert_eq!(data[0], 0x34); 511 } 512 513 #[test] 514 fn serial_modem() { 515 let intr_evt = EventFd::new(0).unwrap(); 516 let mut serial = Serial::new_sink( 517 String::from(SERIAL_NAME), 518 Arc::new(TestInterrupt::new(intr_evt.try_clone().unwrap())), 519 None, 520 ); 521 522 serial.write(0, MCR as u64, &[MCR_LOOP_BIT]); 523 serial.write(0, DATA as u64, &[b'a']); 524 serial.write(0, DATA as u64, &[b'b']); 525 serial.write(0, DATA as u64, &[b'c']); 526 527 let mut data = [0u8]; 528 serial.read(0, MSR as u64, &mut data[..]); 529 assert_eq!(data[0], DEFAULT_MODEM_STATUS); 530 serial.read(0, MCR as u64, &mut data[..]); 531 assert_eq!(data[0], MCR_LOOP_BIT); 532 serial.read(0, DATA as u64, &mut data[..]); 533 assert_eq!(data[0], b'a'); 534 serial.read(0, DATA as u64, &mut data[..]); 535 assert_eq!(data[0], b'b'); 536 serial.read(0, DATA as u64, &mut data[..]); 537 assert_eq!(data[0], b'c'); 538 } 539 540 #[test] 541 fn serial_scratch() { 542 let intr_evt = EventFd::new(0).unwrap(); 543 let mut serial = Serial::new_sink( 544 String::from(SERIAL_NAME), 545 Arc::new(TestInterrupt::new(intr_evt.try_clone().unwrap())), 546 None, 547 ); 548 549 serial.write(0, SCR as u64, &[0x12]); 550 551 let mut data = [0u8]; 552 serial.read(0, SCR as u64, &mut data[..]); 553 assert_eq!(data[0], 0x12); 554 } 555 } 556