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