xref: /cloud-hypervisor/devices/src/legacy/serial.rs (revision b440cb7d2330770cd415b63544a371d4caa2db3a)
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