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