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