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 12 use serde::{Deserialize, Serialize}; 13 use vm_device::interrupt::InterruptSourceGroup; 14 use vm_device::BusDevice; 15 use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable}; 16 use vmm_sys_util::errno::Result; 17 18 const LOOP_SIZE: usize = 0x40; 19 20 const DATA: u8 = 0; 21 const IER: u8 = 1; 22 const IIR: u8 = 2; 23 const LCR: u8 = 3; 24 const MCR: u8 = 4; 25 const LSR: u8 = 5; 26 const MSR: u8 = 6; 27 const SCR: u8 = 7; 28 29 const DLAB_LOW: u8 = 0; 30 const DLAB_HIGH: u8 = 1; 31 32 const IER_RECV_BIT: u8 = 0x1; 33 const IER_THR_BIT: u8 = 0x2; 34 const IER_FIFO_BITS: u8 = 0x0f; 35 36 const IIR_FIFO_BITS: u8 = 0xc0; 37 const IIR_NONE_BIT: u8 = 0x1; 38 const IIR_THR_BIT: u8 = 0x2; 39 const IIR_RECV_BIT: u8 = 0x4; 40 41 const LCR_DLAB_BIT: u8 = 0x80; 42 43 const LSR_DATA_BIT: u8 = 0x1; 44 const LSR_EMPTY_BIT: u8 = 0x20; 45 const LSR_IDLE_BIT: u8 = 0x40; 46 47 const MCR_LOOP_BIT: u8 = 0x10; 48 49 const DEFAULT_INTERRUPT_IDENTIFICATION: u8 = IIR_NONE_BIT; // no pending interrupt 50 const DEFAULT_LINE_STATUS: u8 = LSR_EMPTY_BIT | LSR_IDLE_BIT; // THR empty and line is idle 51 const DEFAULT_LINE_CONTROL: u8 = 0x3; // 8-bits per character 52 const DEFAULT_MODEM_CONTROL: u8 = 0x8; // Auxiliary output 2 53 const DEFAULT_MODEM_STATUS: u8 = 0x20 | 0x10 | 0x80; // data ready, clear to send, carrier detect 54 const DEFAULT_BAUD_DIVISOR: u16 = 12; // 9600 bps 55 56 /// Emulates serial COM ports commonly seen on x86 I/O ports 0x3f8/0x2f8/0x3e8/0x2e8. 57 /// 58 /// This can optionally write the guest's output to a Write trait object. To send input to the 59 /// guest, use `queue_input_bytes`. 60 pub struct Serial { 61 id: String, 62 interrupt_enable: u8, 63 interrupt_identification: u8, 64 line_control: u8, 65 line_status: u8, 66 modem_control: u8, 67 modem_status: u8, 68 scratch: u8, 69 baud_divisor: u16, 70 in_buffer: VecDeque<u8>, 71 interrupt: Arc<dyn InterruptSourceGroup>, 72 out: Option<Box<dyn io::Write + Send>>, 73 } 74 75 #[derive(Serialize, Deserialize)] 76 pub struct SerialState { 77 interrupt_enable: u8, 78 interrupt_identification: u8, 79 line_control: u8, 80 line_status: u8, 81 modem_control: u8, 82 modem_status: u8, 83 scratch: u8, 84 baud_divisor: u16, 85 in_buffer: Vec<u8>, 86 } 87 88 impl Serial { new( id: String, interrupt: Arc<dyn InterruptSourceGroup>, out: Option<Box<dyn io::Write + Send>>, state: Option<SerialState>, ) -> Serial89 pub fn new( 90 id: String, 91 interrupt: Arc<dyn InterruptSourceGroup>, 92 out: Option<Box<dyn io::Write + Send>>, 93 state: Option<SerialState>, 94 ) -> Serial { 95 let ( 96 interrupt_enable, 97 interrupt_identification, 98 line_control, 99 line_status, 100 modem_control, 101 modem_status, 102 scratch, 103 baud_divisor, 104 in_buffer, 105 ) = if let Some(state) = state { 106 ( 107 state.interrupt_enable, 108 state.interrupt_identification, 109 state.line_control, 110 state.line_status, 111 state.modem_control, 112 state.modem_status, 113 state.scratch, 114 state.baud_divisor, 115 state.in_buffer.into(), 116 ) 117 } else { 118 ( 119 0, 120 DEFAULT_INTERRUPT_IDENTIFICATION, 121 DEFAULT_LINE_CONTROL, 122 DEFAULT_LINE_STATUS, 123 DEFAULT_MODEM_CONTROL, 124 DEFAULT_MODEM_STATUS, 125 0, 126 DEFAULT_BAUD_DIVISOR, 127 VecDeque::new(), 128 ) 129 }; 130 131 Serial { 132 id, 133 interrupt_enable, 134 interrupt_identification, 135 line_control, 136 line_status, 137 modem_control, 138 modem_status, 139 scratch, 140 baud_divisor, 141 in_buffer, 142 interrupt, 143 out, 144 } 145 } 146 147 /// Constructs a Serial port ready for output. new_out( id: String, interrupt: Arc<dyn InterruptSourceGroup>, out: Box<dyn io::Write + Send>, state: Option<SerialState>, ) -> Serial148 pub fn new_out( 149 id: String, 150 interrupt: Arc<dyn InterruptSourceGroup>, 151 out: Box<dyn io::Write + Send>, 152 state: Option<SerialState>, 153 ) -> Serial { 154 Self::new(id, interrupt, Some(out), state) 155 } 156 157 /// Constructs a Serial port with no connected output. new_sink( id: String, interrupt: Arc<dyn InterruptSourceGroup>, state: Option<SerialState>, ) -> Serial158 pub fn new_sink( 159 id: String, 160 interrupt: Arc<dyn InterruptSourceGroup>, 161 state: Option<SerialState>, 162 ) -> Serial { 163 Self::new(id, interrupt, None, state) 164 } 165 set_out(&mut self, out: Option<Box<dyn io::Write + Send>>)166 pub fn set_out(&mut self, out: Option<Box<dyn io::Write + Send>>) { 167 self.out = out; 168 } 169 170 /// Queues raw bytes for the guest to read and signals the interrupt if the line status would 171 /// change. queue_input_bytes(&mut self, c: &[u8]) -> Result<()>172 pub fn queue_input_bytes(&mut self, c: &[u8]) -> Result<()> { 173 if !self.is_loop() { 174 self.in_buffer.extend(c); 175 self.recv_data()?; 176 } 177 Ok(()) 178 } 179 flush_output(&mut self) -> result::Result<(), io::Error>180 pub fn flush_output(&mut self) -> result::Result<(), io::Error> { 181 if let Some(out) = self.out.as_mut() { 182 out.flush()?; 183 } 184 Ok(()) 185 } 186 is_dlab_set(&self) -> bool187 fn is_dlab_set(&self) -> bool { 188 (self.line_control & LCR_DLAB_BIT) != 0 189 } 190 is_recv_intr_enabled(&self) -> bool191 fn is_recv_intr_enabled(&self) -> bool { 192 (self.interrupt_enable & IER_RECV_BIT) != 0 193 } 194 is_thr_intr_enabled(&self) -> bool195 fn is_thr_intr_enabled(&self) -> bool { 196 (self.interrupt_enable & IER_THR_BIT) != 0 197 } 198 is_loop(&self) -> bool199 fn is_loop(&self) -> bool { 200 (self.modem_control & MCR_LOOP_BIT) != 0 201 } 202 add_intr_bit(&mut self, bit: u8)203 fn add_intr_bit(&mut self, bit: u8) { 204 self.interrupt_identification &= !IIR_NONE_BIT; 205 self.interrupt_identification |= bit; 206 } 207 del_intr_bit(&mut self, bit: u8)208 fn del_intr_bit(&mut self, bit: u8) { 209 self.interrupt_identification &= !bit; 210 if self.interrupt_identification == 0x0 { 211 self.interrupt_identification = IIR_NONE_BIT; 212 } 213 } 214 thr_empty(&mut self) -> Result<()>215 fn thr_empty(&mut self) -> Result<()> { 216 if self.is_thr_intr_enabled() { 217 self.add_intr_bit(IIR_THR_BIT); 218 self.trigger_interrupt()? 219 } 220 Ok(()) 221 } 222 recv_data(&mut self) -> Result<()>223 fn recv_data(&mut self) -> Result<()> { 224 if self.is_recv_intr_enabled() { 225 self.add_intr_bit(IIR_RECV_BIT); 226 self.trigger_interrupt()? 227 } 228 self.line_status |= LSR_DATA_BIT; 229 Ok(()) 230 } 231 trigger_interrupt(&mut self) -> result::Result<(), io::Error>232 fn trigger_interrupt(&mut self) -> result::Result<(), io::Error> { 233 self.interrupt.trigger(0) 234 } 235 iir_reset(&mut self)236 fn iir_reset(&mut self) { 237 self.interrupt_identification = DEFAULT_INTERRUPT_IDENTIFICATION; 238 } 239 handle_write(&mut self, offset: u8, v: u8) -> Result<()>240 fn handle_write(&mut self, offset: u8, v: u8) -> Result<()> { 241 match offset { 242 DLAB_LOW if self.is_dlab_set() => { 243 self.baud_divisor = (self.baud_divisor & 0xff00) | u16::from(v) 244 } 245 DLAB_HIGH if self.is_dlab_set() => { 246 self.baud_divisor = (self.baud_divisor & 0x00ff) | ((u16::from(v)) << 8) 247 } 248 DATA => { 249 if self.is_loop() { 250 if self.in_buffer.len() < LOOP_SIZE { 251 self.in_buffer.push_back(v); 252 self.recv_data()?; 253 } 254 } else { 255 if let Some(out) = self.out.as_mut() { 256 out.write_all(&[v])?; 257 out.flush()?; 258 } 259 self.thr_empty()?; 260 } 261 } 262 IER => self.interrupt_enable = v & IER_FIFO_BITS, 263 LCR => self.line_control = v, 264 MCR => self.modem_control = v, 265 SCR => self.scratch = v, 266 _ => {} 267 } 268 Ok(()) 269 } 270 state(&self) -> SerialState271 fn state(&self) -> SerialState { 272 SerialState { 273 interrupt_enable: self.interrupt_enable, 274 interrupt_identification: self.interrupt_identification, 275 line_control: self.line_control, 276 line_status: self.line_status, 277 modem_control: self.modem_control, 278 modem_status: self.modem_status, 279 scratch: self.scratch, 280 baud_divisor: self.baud_divisor, 281 in_buffer: self.in_buffer.clone().into(), 282 } 283 } 284 } 285 286 impl BusDevice for Serial { read(&mut self, _base: u64, offset: u64, data: &mut [u8])287 fn read(&mut self, _base: u64, offset: u64, data: &mut [u8]) { 288 if data.len() != 1 { 289 return; 290 } 291 292 data[0] = match offset as u8 { 293 DLAB_LOW if self.is_dlab_set() => self.baud_divisor as u8, 294 DLAB_HIGH if self.is_dlab_set() => (self.baud_divisor >> 8) as u8, 295 DATA => { 296 self.del_intr_bit(IIR_RECV_BIT); 297 if self.in_buffer.len() <= 1 { 298 self.line_status &= !LSR_DATA_BIT; 299 } 300 self.in_buffer.pop_front().unwrap_or_default() 301 } 302 IER => self.interrupt_enable, 303 IIR => { 304 let v = self.interrupt_identification | IIR_FIFO_BITS; 305 self.iir_reset(); 306 v 307 } 308 LCR => self.line_control, 309 MCR => self.modem_control, 310 LSR => self.line_status, 311 MSR => self.modem_status, 312 SCR => self.scratch, 313 _ => 0, 314 }; 315 } 316 write(&mut self, _base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>>317 fn write(&mut self, _base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> { 318 if data.len() != 1 { 319 return None; 320 } 321 322 self.handle_write(offset as u8, data[0]).ok(); 323 324 None 325 } 326 } 327 328 impl Snapshottable for Serial { id(&self) -> String329 fn id(&self) -> String { 330 self.id.clone() 331 } 332 snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError>333 fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> { 334 Snapshot::new_from_state(&self.state()) 335 } 336 } 337 338 impl Pausable for Serial {} 339 impl Transportable for Serial {} 340 impl Migratable for Serial {} 341 342 #[cfg(test)] 343 mod tests { 344 use std::sync::Mutex; 345 346 use vm_device::interrupt::{InterruptIndex, InterruptSourceConfig}; 347 use vmm_sys_util::eventfd::EventFd; 348 349 use super::*; 350 351 const SERIAL_NAME: &str = "serial"; 352 353 struct TestInterrupt { 354 event_fd: EventFd, 355 } 356 357 impl InterruptSourceGroup for TestInterrupt { trigger(&self, _index: InterruptIndex) -> result::Result<(), std::io::Error>358 fn trigger(&self, _index: InterruptIndex) -> result::Result<(), std::io::Error> { 359 self.event_fd.write(1) 360 } update( &self, _index: InterruptIndex, _config: InterruptSourceConfig, _masked: bool, _set_gsi: bool, ) -> result::Result<(), std::io::Error>361 fn update( 362 &self, 363 _index: InterruptIndex, 364 _config: InterruptSourceConfig, 365 _masked: bool, 366 _set_gsi: bool, 367 ) -> result::Result<(), std::io::Error> { 368 Ok(()) 369 } set_gsi(&self) -> result::Result<(), std::io::Error>370 fn set_gsi(&self) -> result::Result<(), std::io::Error> { 371 Ok(()) 372 } notifier(&self, _index: InterruptIndex) -> Option<EventFd>373 fn notifier(&self, _index: InterruptIndex) -> Option<EventFd> { 374 Some(self.event_fd.try_clone().unwrap()) 375 } 376 } 377 378 impl TestInterrupt { new(event_fd: EventFd) -> Self379 fn new(event_fd: EventFd) -> Self { 380 TestInterrupt { event_fd } 381 } 382 } 383 384 #[derive(Clone)] 385 struct SharedBuffer { 386 buf: Arc<Mutex<Vec<u8>>>, 387 } 388 389 impl SharedBuffer { new() -> SharedBuffer390 fn new() -> SharedBuffer { 391 SharedBuffer { 392 buf: Arc::new(Mutex::new(Vec::new())), 393 } 394 } 395 } 396 397 impl io::Write for SharedBuffer { write(&mut self, buf: &[u8]) -> io::Result<usize>398 fn write(&mut self, buf: &[u8]) -> io::Result<usize> { 399 self.buf.lock().unwrap().write(buf) 400 } flush(&mut self) -> io::Result<()>401 fn flush(&mut self) -> io::Result<()> { 402 self.buf.lock().unwrap().flush() 403 } 404 } 405 406 #[test] serial_output()407 fn serial_output() { 408 let intr_evt = EventFd::new(0).unwrap(); 409 let serial_out = SharedBuffer::new(); 410 let mut serial = Serial::new_out( 411 String::from(SERIAL_NAME), 412 Arc::new(TestInterrupt::new(intr_evt.try_clone().unwrap())), 413 Box::new(serial_out.clone()), 414 None, 415 ); 416 417 serial.write(0, DATA as u64, b"xy"); 418 serial.write(0, DATA as u64, b"a"); 419 serial.write(0, DATA as u64, b"b"); 420 serial.write(0, DATA as u64, b"c"); 421 assert_eq!(serial_out.buf.lock().unwrap().as_slice(), b"abc"); 422 } 423 424 #[test] serial_input()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 intr_evt.write(1).unwrap(); 438 serial.write(0, IER as u64, &[IER_RECV_BIT]); 439 serial.queue_input_bytes(b"abc").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] serial_thr()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 intr_evt.write(1).unwrap(); 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] serial_dlab()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] serial_modem()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] serial_scratch()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