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