xref: /cloud-hypervisor/devices/src/legacy/uart_pl011.rs (revision 7d7bfb2034001d4cb15df2ddc56d2d350c8da30f)
1 // Copyright 2021 Arm Limited (or its affiliates). All rights reserved.
2 // SPDX-License-Identifier: Apache-2.0
3 
4 //! ARM PrimeCell UART(PL011)
5 //!
6 //! This module implements an ARM PrimeCell UART(PL011).
7 //!
8 
9 use crate::{read_le_u32, write_le_u32};
10 use std::collections::VecDeque;
11 use std::fmt;
12 use std::sync::{Arc, Barrier};
13 use std::{io, result};
14 use versionize::{VersionMap, Versionize, VersionizeResult};
15 use versionize_derive::Versionize;
16 use vm_device::interrupt::InterruptSourceGroup;
17 use vm_device::BusDevice;
18 use vm_migration::{
19     Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable, VersionMapped,
20 };
21 
22 /* Registers */
23 const UARTDR: u64 = 0;
24 const UARTRSR_UARTECR: u64 = 1;
25 const UARTFR: u64 = 6;
26 const UARTILPR: u64 = 8;
27 const UARTIBRD: u64 = 9;
28 const UARTFBRD: u64 = 10;
29 const UARTLCR_H: u64 = 11;
30 const UARTCR: u64 = 12;
31 const UARTIFLS: u64 = 13;
32 const UARTIMSC: u64 = 14;
33 const UARTRIS: u64 = 15;
34 const UARTMIS: u64 = 16;
35 const UARTICR: u64 = 17;
36 const UARTDMACR: u64 = 18;
37 const UARTDEBUG: u64 = 0x3c0;
38 
39 const PL011_INT_TX: u32 = 0x20;
40 const PL011_INT_RX: u32 = 0x10;
41 
42 const PL011_FLAG_RXFF: u32 = 0x40;
43 const PL011_FLAG_RXFE: u32 = 0x10;
44 
45 const PL011_ID: [u8; 8] = [0x11, 0x10, 0x14, 0x00, 0x0d, 0xf0, 0x05, 0xb1];
46 // We are only interested in the margins.
47 const AMBA_ID_LOW: u64 = 0x3f8;
48 const AMBA_ID_HIGH: u64 = 0x401;
49 
50 #[derive(Debug)]
51 pub enum Error {
52     BadWriteOffset(u64),
53     DmaNotImplemented,
54     InterruptFailure(io::Error),
55     WriteAllFailure(io::Error),
56     FlushFailure(io::Error),
57 }
58 
59 impl fmt::Display for Error {
60     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
61         match self {
62             Error::BadWriteOffset(offset) => write!(f, "pl011_write: Bad Write Offset: {}", offset),
63             Error::DmaNotImplemented => write!(f, "pl011: DMA not implemented."),
64             Error::InterruptFailure(e) => write!(f, "Failed to trigger interrupt: {}", e),
65             Error::WriteAllFailure(e) => write!(f, "Failed to write: {}", e),
66             Error::FlushFailure(e) => write!(f, "Failed to flush: {}", e),
67         }
68     }
69 }
70 
71 type Result<T> = result::Result<T, Error>;
72 
73 /// A PL011 device following the PL011 specification.
74 pub struct Pl011 {
75     id: String,
76     flags: u32,
77     lcr: u32,
78     rsr: u32,
79     cr: u32,
80     dmacr: u32,
81     debug: u32,
82     int_enabled: u32,
83     int_level: u32,
84     read_fifo: VecDeque<u8>,
85     ilpr: u32,
86     ibrd: u32,
87     fbrd: u32,
88     ifl: u32,
89     read_count: u32,
90     read_trigger: u32,
91     irq: Arc<dyn InterruptSourceGroup>,
92     out: Option<Box<dyn io::Write + Send>>,
93     timestamp: std::time::Instant,
94 }
95 
96 #[derive(Versionize)]
97 pub struct Pl011State {
98     flags: u32,
99     lcr: u32,
100     rsr: u32,
101     cr: u32,
102     dmacr: u32,
103     debug: u32,
104     int_enabled: u32,
105     int_level: u32,
106     read_fifo: Vec<u8>,
107     ilpr: u32,
108     ibrd: u32,
109     fbrd: u32,
110     ifl: u32,
111     read_count: u32,
112     read_trigger: u32,
113 }
114 
115 impl VersionMapped for Pl011State {}
116 
117 impl Pl011 {
118     /// Constructs an AMBA PL011 UART device.
119     pub fn new(
120         id: String,
121         irq: Arc<dyn InterruptSourceGroup>,
122         out: Option<Box<dyn io::Write + Send>>,
123     ) -> Self {
124         Self {
125             id,
126             flags: 0x90u32,
127             lcr: 0u32,
128             rsr: 0u32,
129             cr: 0x300u32,
130             dmacr: 0u32,
131             debug: 0u32,
132             int_enabled: 0u32,
133             int_level: 0u32,
134             read_fifo: VecDeque::new(),
135             ilpr: 0u32,
136             ibrd: 0u32,
137             fbrd: 0u32,
138             ifl: 0x12u32,
139             read_count: 0u32,
140             read_trigger: 1u32,
141             irq,
142             out,
143             timestamp: std::time::Instant::now(),
144         }
145     }
146 
147     pub fn set_out(&mut self, out: Box<dyn io::Write + Send>) {
148         self.out = Some(out);
149     }
150 
151     fn state(&self) -> Pl011State {
152         Pl011State {
153             flags: self.flags,
154             lcr: self.lcr,
155             rsr: self.rsr,
156             cr: self.cr,
157             dmacr: self.dmacr,
158             debug: self.debug,
159             int_enabled: self.int_enabled,
160             int_level: self.int_level,
161             read_fifo: self.read_fifo.clone().into(),
162             ilpr: self.ilpr,
163             ibrd: self.ibrd,
164             fbrd: self.fbrd,
165             ifl: self.ifl,
166             read_count: self.read_count,
167             read_trigger: self.read_trigger,
168         }
169     }
170 
171     fn set_state(&mut self, state: &Pl011State) {
172         self.flags = state.flags;
173         self.lcr = state.lcr;
174         self.rsr = state.rsr;
175         self.cr = state.cr;
176         self.dmacr = state.dmacr;
177         self.debug = state.debug;
178         self.int_enabled = state.int_enabled;
179         self.int_level = state.int_level;
180         self.read_fifo = state.read_fifo.clone().into();
181         self.ilpr = state.ilpr;
182         self.ibrd = state.ibrd;
183         self.fbrd = state.fbrd;
184         self.ifl = state.ifl;
185         self.read_count = state.read_count;
186         self.read_trigger = state.read_trigger;
187     }
188 
189     /// Queues raw bytes for the guest to read and signals the interrupt
190     pub fn queue_input_bytes(&mut self, c: &[u8]) -> vmm_sys_util::errno::Result<()> {
191         self.read_fifo.extend(c);
192         self.read_count += c.len() as u32;
193         self.flags &= !PL011_FLAG_RXFE;
194 
195         if ((self.lcr & 0x10) == 0) || (self.read_count == 16) {
196             self.flags |= PL011_FLAG_RXFF;
197         }
198 
199         if self.read_count >= self.read_trigger {
200             self.int_level |= PL011_INT_RX;
201             self.trigger_interrupt()?;
202         }
203 
204         Ok(())
205     }
206 
207     pub fn flush_output(&mut self) -> result::Result<(), io::Error> {
208         if let Some(out) = self.out.as_mut() {
209             out.flush()?;
210         }
211         Ok(())
212     }
213 
214     fn pl011_get_baudrate(&self) -> u32 {
215         if self.fbrd == 0 {
216             return 0;
217         }
218 
219         let clk = 24_000_000; // We set the APB_PLCK to 24M in device tree
220         (clk / ((self.ibrd << 6) + self.fbrd)) << 2
221     }
222 
223     fn pl011_trace_baudrate_change(&self) {
224         debug!(
225             "=== New baudrate: {:#?} (clk: {:#?}Hz, ibrd: {:#?}, fbrd: {:#?}) ===",
226             self.pl011_get_baudrate(),
227             24_000_000, // We set the APB_PLCK to 24M in device tree
228             self.ibrd,
229             self.fbrd
230         );
231     }
232 
233     fn pl011_set_read_trigger(&mut self) {
234         self.read_trigger = 1;
235     }
236 
237     fn handle_write(&mut self, offset: u64, val: u32) -> Result<()> {
238         match offset >> 2 {
239             UARTDR => {
240                 self.int_level |= PL011_INT_TX;
241                 if let Some(out) = self.out.as_mut() {
242                     out.write_all(&[val.to_le_bytes()[0]])
243                         .map_err(Error::WriteAllFailure)?;
244                     out.flush().map_err(Error::FlushFailure)?;
245                 }
246             }
247             UARTRSR_UARTECR => {
248                 self.rsr = 0;
249             }
250             UARTFR => { /* Writes to Flag register are ignored.*/ }
251             UARTILPR => {
252                 self.ilpr = val;
253             }
254             UARTIBRD => {
255                 self.ibrd = val;
256                 self.pl011_trace_baudrate_change();
257             }
258             UARTFBRD => {
259                 self.fbrd = val;
260                 self.pl011_trace_baudrate_change();
261             }
262             UARTLCR_H => {
263                 /* Reset the FIFO state on FIFO enable or disable */
264                 if ((self.lcr ^ val) & 0x10) != 0 {
265                     self.read_count = 0;
266                 }
267                 self.lcr = val;
268                 self.pl011_set_read_trigger();
269             }
270             UARTCR => {
271                 self.cr = val;
272             }
273             UARTIFLS => {
274                 self.ifl = val;
275                 self.pl011_set_read_trigger();
276             }
277             UARTIMSC => {
278                 self.int_enabled = val;
279                 self.trigger_interrupt().map_err(Error::InterruptFailure)?;
280             }
281             UARTICR => {
282                 self.int_level &= !val;
283                 self.trigger_interrupt().map_err(Error::InterruptFailure)?;
284             }
285             UARTDMACR => {
286                 self.dmacr = val;
287                 if (val & 3) != 0 {
288                     return Err(Error::DmaNotImplemented);
289                 }
290             }
291             UARTDEBUG => {
292                 self.debug = val;
293                 self.handle_debug();
294             }
295             off => {
296                 debug!("PL011: Bad write offset, offset: {}", off);
297                 return Err(Error::BadWriteOffset(off));
298             }
299         }
300         Ok(())
301     }
302 
303     fn handle_debug(&self) {
304         let elapsed = self.timestamp.elapsed();
305 
306         match self.debug {
307             0x00..=0x1f => info!(
308                 "[Debug I/O port: Firmware code: 0x{:x}] {}.{:>06} seconds",
309                 self.debug,
310                 elapsed.as_secs(),
311                 elapsed.as_micros()
312             ),
313             0x20..=0x3f => info!(
314                 "[Debug I/O port: Bootloader code: 0x{:x}] {}.{:>06} seconds",
315                 self.debug,
316                 elapsed.as_secs(),
317                 elapsed.as_micros()
318             ),
319             0x40..=0x5f => info!(
320                 "[Debug I/O port: Kernel code: 0x{:x}] {}.{:>06} seconds",
321                 self.debug,
322                 elapsed.as_secs(),
323                 elapsed.as_micros()
324             ),
325             0x60..=0x7f => info!(
326                 "[Debug I/O port: Userspace code: 0x{:x}] {}.{:>06} seconds",
327                 self.debug,
328                 elapsed.as_secs(),
329                 elapsed.as_micros()
330             ),
331             _ => {}
332         }
333     }
334 
335     fn trigger_interrupt(&mut self) -> result::Result<(), io::Error> {
336         self.irq.trigger(0)
337     }
338 }
339 
340 impl BusDevice for Pl011 {
341     fn read(&mut self, _base: u64, offset: u64, data: &mut [u8]) {
342         let mut read_ok = true;
343         let v = if (AMBA_ID_LOW..AMBA_ID_HIGH).contains(&(offset >> 2)) {
344             let index = ((offset - 0xfe0) >> 2) as usize;
345             u32::from(PL011_ID[index])
346         } else {
347             match offset >> 2 {
348                 UARTDR => {
349                     self.flags &= !PL011_FLAG_RXFF;
350                     let c: u32 = self.read_fifo.pop_front().unwrap_or_default().into();
351                     if self.read_count > 0 {
352                         self.read_count -= 1;
353                     }
354                     if self.read_count == 0 {
355                         self.flags |= PL011_FLAG_RXFE;
356                     }
357                     if self.read_count == (self.read_trigger - 1) {
358                         self.int_level &= !PL011_INT_RX;
359                     }
360                     self.rsr = c >> 8;
361                     c
362                 }
363                 UARTRSR_UARTECR => self.rsr,
364                 UARTFR => self.flags,
365                 UARTILPR => self.ilpr,
366                 UARTIBRD => self.ibrd,
367                 UARTFBRD => self.fbrd,
368                 UARTLCR_H => self.lcr,
369                 UARTCR => self.cr,
370                 UARTIFLS => self.ifl,
371                 UARTIMSC => self.int_enabled,
372                 UARTRIS => self.int_level,
373                 UARTMIS => (self.int_level & self.int_enabled),
374                 UARTDMACR => self.dmacr,
375                 UARTDEBUG => self.debug,
376                 _ => {
377                     read_ok = false;
378                     0
379                 }
380             }
381         };
382 
383         if read_ok && data.len() <= 4 {
384             write_le_u32(data, v);
385         } else {
386             warn!(
387                 "Invalid PL011 read: offset {}, data length {}",
388                 offset,
389                 data.len()
390             );
391         }
392     }
393 
394     fn write(&mut self, _base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> {
395         if data.len() <= 4 {
396             let v = read_le_u32(data);
397             if let Err(e) = self.handle_write(offset, v) {
398                 warn!("Failed to write to PL011 device: {}", e);
399             }
400         } else {
401             warn!(
402                 "Invalid PL011 write: offset {}, data length {}",
403                 offset,
404                 data.len()
405             );
406         }
407 
408         None
409     }
410 }
411 
412 impl Snapshottable for Pl011 {
413     fn id(&self) -> String {
414         self.id.clone()
415     }
416 
417     fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
418         Snapshot::new_from_versioned_state(&self.id, &self.state())
419     }
420 
421     fn restore(&mut self, snapshot: Snapshot) -> std::result::Result<(), MigratableError> {
422         self.set_state(&snapshot.to_versioned_state(&self.id)?);
423         Ok(())
424     }
425 }
426 
427 impl Pausable for Pl011 {}
428 impl Transportable for Pl011 {}
429 impl Migratable for Pl011 {}
430 
431 #[cfg(test)]
432 mod tests {
433     use super::*;
434     use std::io;
435     use std::sync::{Arc, Mutex};
436     use vm_device::interrupt::{InterruptIndex, InterruptSourceConfig};
437     use vmm_sys_util::eventfd::EventFd;
438 
439     const SERIAL_NAME: &str = "serial";
440 
441     struct TestInterrupt {
442         event_fd: EventFd,
443     }
444 
445     impl InterruptSourceGroup for TestInterrupt {
446         fn trigger(&self, _index: InterruptIndex) -> result::Result<(), std::io::Error> {
447             self.event_fd.write(1)
448         }
449         fn update(
450             &self,
451             _index: InterruptIndex,
452             _config: InterruptSourceConfig,
453         ) -> result::Result<(), std::io::Error> {
454             Ok(())
455         }
456         fn notifier(&self, _index: InterruptIndex) -> Option<EventFd> {
457             Some(self.event_fd.try_clone().unwrap())
458         }
459     }
460 
461     impl TestInterrupt {
462         fn new(event_fd: EventFd) -> Self {
463             TestInterrupt { event_fd }
464         }
465     }
466 
467     #[derive(Clone)]
468     struct SharedBuffer {
469         buf: Arc<Mutex<Vec<u8>>>,
470     }
471 
472     impl SharedBuffer {
473         fn new() -> SharedBuffer {
474             SharedBuffer {
475                 buf: Arc::new(Mutex::new(Vec::new())),
476             }
477         }
478     }
479 
480     impl io::Write for SharedBuffer {
481         fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
482             self.buf.lock().unwrap().write(buf)
483         }
484         fn flush(&mut self) -> io::Result<()> {
485             self.buf.lock().unwrap().flush()
486         }
487     }
488 
489     #[test]
490     fn pl011_output() {
491         let intr_evt = EventFd::new(0).unwrap();
492         let pl011_out = SharedBuffer::new();
493         let mut pl011 = Pl011::new(
494             String::from(SERIAL_NAME),
495             Arc::new(TestInterrupt::new(intr_evt.try_clone().unwrap())),
496             Some(Box::new(pl011_out.clone())),
497         );
498 
499         pl011.write(0, UARTDR as u64, &[b'x', b'y']);
500         pl011.write(0, UARTDR as u64, &[b'a']);
501         pl011.write(0, UARTDR as u64, &[b'b']);
502         pl011.write(0, UARTDR as u64, &[b'c']);
503         assert_eq!(
504             pl011_out.buf.lock().unwrap().as_slice(),
505             &[b'x', b'a', b'b', b'c']
506         );
507     }
508 
509     #[test]
510     fn pl011_input() {
511         let intr_evt = EventFd::new(0).unwrap();
512         let pl011_out = SharedBuffer::new();
513         let mut pl011 = Pl011::new(
514             String::from(SERIAL_NAME),
515             Arc::new(TestInterrupt::new(intr_evt.try_clone().unwrap())),
516             Some(Box::new(pl011_out)),
517         );
518 
519         // write 1 to the interrupt event fd, so that read doesn't block in case the event fd
520         // counter doesn't change (for 0 it blocks)
521         assert!(intr_evt.write(1).is_ok());
522         pl011.queue_input_bytes(&[b'a', b'b', b'c']).unwrap();
523 
524         assert_eq!(intr_evt.read().unwrap(), 2);
525 
526         let mut data = [0u8];
527         pl011.read(0, UARTDR as u64, &mut data);
528         assert_eq!(data[0], b'a');
529         pl011.read(0, UARTDR as u64, &mut data);
530         assert_eq!(data[0], b'b');
531         pl011.read(0, UARTDR as u64, &mut data);
532         assert_eq!(data[0], b'c');
533     }
534 }
535