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