xref: /cloud-hypervisor/devices/src/legacy/uart_pl011.rs (revision 5e52729453cb62edbe4fb3a4aa24f8cca31e667e)
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         state: Option<Pl011State>,
126     ) -> Self {
127         let (
128             flags,
129             lcr,
130             rsr,
131             cr,
132             dmacr,
133             debug,
134             int_enabled,
135             int_level,
136             read_fifo,
137             ilpr,
138             ibrd,
139             fbrd,
140             ifl,
141             read_count,
142             read_trigger,
143         ) = if let Some(state) = state {
144             (
145                 state.flags,
146                 state.lcr,
147                 state.rsr,
148                 state.cr,
149                 state.dmacr,
150                 state.debug,
151                 state.int_enabled,
152                 state.int_level,
153                 state.read_fifo.into(),
154                 state.ilpr,
155                 state.ibrd,
156                 state.fbrd,
157                 state.ifl,
158                 state.read_count,
159                 state.read_trigger,
160             )
161         } else {
162             (
163                 0x90,
164                 0,
165                 0,
166                 0x300,
167                 0,
168                 0,
169                 0,
170                 0,
171                 VecDeque::new(),
172                 0,
173                 0,
174                 0,
175                 0x12,
176                 0,
177                 1,
178             )
179         };
180 
181         Self {
182             id,
183             flags,
184             lcr,
185             rsr,
186             cr,
187             dmacr,
188             debug,
189             int_enabled,
190             int_level,
191             read_fifo,
192             ilpr,
193             ibrd,
194             fbrd,
195             ifl,
196             read_count,
197             read_trigger,
198             irq,
199             out,
200             timestamp,
201         }
202     }
203 
204     pub fn set_out(&mut self, out: Box<dyn io::Write + Send>) {
205         self.out = Some(out);
206     }
207 
208     fn state(&self) -> Pl011State {
209         Pl011State {
210             flags: self.flags,
211             lcr: self.lcr,
212             rsr: self.rsr,
213             cr: self.cr,
214             dmacr: self.dmacr,
215             debug: self.debug,
216             int_enabled: self.int_enabled,
217             int_level: self.int_level,
218             read_fifo: self.read_fifo.clone().into(),
219             ilpr: self.ilpr,
220             ibrd: self.ibrd,
221             fbrd: self.fbrd,
222             ifl: self.ifl,
223             read_count: self.read_count,
224             read_trigger: self.read_trigger,
225         }
226     }
227 
228     /// Queues raw bytes for the guest to read and signals the interrupt
229     pub fn queue_input_bytes(&mut self, c: &[u8]) -> vmm_sys_util::errno::Result<()> {
230         self.read_fifo.extend(c);
231         self.read_count += c.len() as u32;
232         self.flags &= !PL011_FLAG_RXFE;
233 
234         if ((self.lcr & 0x10) == 0) || (self.read_count == 16) {
235             self.flags |= PL011_FLAG_RXFF;
236         }
237 
238         if self.read_count >= self.read_trigger {
239             self.int_level |= PL011_INT_RX;
240             self.trigger_interrupt()?;
241         }
242 
243         Ok(())
244     }
245 
246     pub fn flush_output(&mut self) -> result::Result<(), io::Error> {
247         if let Some(out) = self.out.as_mut() {
248             out.flush()?;
249         }
250         Ok(())
251     }
252 
253     fn pl011_get_baudrate(&self) -> u32 {
254         if self.fbrd == 0 {
255             return 0;
256         }
257 
258         let clk = 24_000_000; // We set the APB_PLCK to 24M in device tree
259         (clk / ((self.ibrd << 6) + self.fbrd)) << 2
260     }
261 
262     fn pl011_trace_baudrate_change(&self) {
263         debug!(
264             "=== New baudrate: {:#?} (clk: {:#?}Hz, ibrd: {:#?}, fbrd: {:#?}) ===",
265             self.pl011_get_baudrate(),
266             24_000_000, // We set the APB_PLCK to 24M in device tree
267             self.ibrd,
268             self.fbrd
269         );
270     }
271 
272     fn pl011_set_read_trigger(&mut self) {
273         self.read_trigger = 1;
274     }
275 
276     fn handle_write(&mut self, offset: u64, val: u32) -> Result<()> {
277         match offset >> 2 {
278             UARTDR => {
279                 self.int_level |= PL011_INT_TX;
280                 if let Some(out) = self.out.as_mut() {
281                     out.write_all(&[val.to_le_bytes()[0]])
282                         .map_err(Error::WriteAllFailure)?;
283                     out.flush().map_err(Error::FlushFailure)?;
284                 }
285             }
286             UARTRSR_UARTECR => {
287                 self.rsr = 0;
288             }
289             UARTFR => { /* Writes to Flag register are ignored.*/ }
290             UARTILPR => {
291                 self.ilpr = val;
292             }
293             UARTIBRD => {
294                 self.ibrd = val;
295                 self.pl011_trace_baudrate_change();
296             }
297             UARTFBRD => {
298                 self.fbrd = val;
299                 self.pl011_trace_baudrate_change();
300             }
301             UARTLCR_H => {
302                 /* Reset the FIFO state on FIFO enable or disable */
303                 if ((self.lcr ^ val) & 0x10) != 0 {
304                     self.read_count = 0;
305                 }
306                 self.lcr = val;
307                 self.pl011_set_read_trigger();
308             }
309             UARTCR => {
310                 self.cr = val;
311             }
312             UARTIFLS => {
313                 self.ifl = val;
314                 self.pl011_set_read_trigger();
315             }
316             UARTIMSC => {
317                 self.int_enabled = val;
318                 self.trigger_interrupt().map_err(Error::InterruptFailure)?;
319             }
320             UARTICR => {
321                 self.int_level &= !val;
322                 self.trigger_interrupt().map_err(Error::InterruptFailure)?;
323             }
324             UARTDMACR => {
325                 self.dmacr = val;
326                 if (val & 3) != 0 {
327                     return Err(Error::DmaNotImplemented);
328                 }
329             }
330             UARTDEBUG => {
331                 self.debug = val;
332                 self.handle_debug();
333             }
334             off => {
335                 debug!("PL011: Bad write offset, offset: {}", off);
336                 return Err(Error::BadWriteOffset(off));
337             }
338         }
339         Ok(())
340     }
341 
342     fn handle_debug(&self) {
343         let elapsed = self.timestamp.elapsed();
344 
345         match self.debug {
346             0x00..=0x1f => warn!(
347                 "[Debug I/O port: Firmware code: 0x{:x}] {}.{:>06} seconds",
348                 self.debug,
349                 elapsed.as_secs(),
350                 elapsed.as_micros()
351             ),
352             0x20..=0x3f => warn!(
353                 "[Debug I/O port: Bootloader code: 0x{:x}] {}.{:>06} seconds",
354                 self.debug,
355                 elapsed.as_secs(),
356                 elapsed.as_micros()
357             ),
358             0x40..=0x5f => warn!(
359                 "[Debug I/O port: Kernel code: 0x{:x}] {}.{:>06} seconds",
360                 self.debug,
361                 elapsed.as_secs(),
362                 elapsed.as_micros()
363             ),
364             0x60..=0x7f => warn!(
365                 "[Debug I/O port: Userspace code: 0x{:x}] {}.{:>06} seconds",
366                 self.debug,
367                 elapsed.as_secs(),
368                 elapsed.as_micros()
369             ),
370             _ => {}
371         }
372     }
373 
374     fn trigger_interrupt(&mut self) -> result::Result<(), io::Error> {
375         self.irq.trigger(0)
376     }
377 }
378 
379 impl BusDevice for Pl011 {
380     fn read(&mut self, _base: u64, offset: u64, data: &mut [u8]) {
381         let mut read_ok = true;
382         let v = if (AMBA_ID_LOW..AMBA_ID_HIGH).contains(&(offset >> 2)) {
383             let index = ((offset - 0xfe0) >> 2) as usize;
384             u32::from(PL011_ID[index])
385         } else {
386             match offset >> 2 {
387                 UARTDR => {
388                     self.flags &= !PL011_FLAG_RXFF;
389                     let c: u32 = self.read_fifo.pop_front().unwrap_or_default().into();
390                     if self.read_count > 0 {
391                         self.read_count -= 1;
392                     }
393                     if self.read_count == 0 {
394                         self.flags |= PL011_FLAG_RXFE;
395                     }
396                     if self.read_count == (self.read_trigger - 1) {
397                         self.int_level &= !PL011_INT_RX;
398                     }
399                     self.rsr = c >> 8;
400                     c
401                 }
402                 UARTRSR_UARTECR => self.rsr,
403                 UARTFR => self.flags,
404                 UARTILPR => self.ilpr,
405                 UARTIBRD => self.ibrd,
406                 UARTFBRD => self.fbrd,
407                 UARTLCR_H => self.lcr,
408                 UARTCR => self.cr,
409                 UARTIFLS => self.ifl,
410                 UARTIMSC => self.int_enabled,
411                 UARTRIS => self.int_level,
412                 UARTMIS => self.int_level & self.int_enabled,
413                 UARTDMACR => self.dmacr,
414                 UARTDEBUG => self.debug,
415                 _ => {
416                     read_ok = false;
417                     0
418                 }
419             }
420         };
421 
422         if read_ok && data.len() <= 4 {
423             write_le_u32(data, v);
424         } else {
425             warn!(
426                 "Invalid PL011 read: offset {}, data length {}",
427                 offset,
428                 data.len()
429             );
430         }
431     }
432 
433     fn write(&mut self, _base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> {
434         if data.len() <= 4 {
435             let v = read_le_u32(data);
436             if let Err(e) = self.handle_write(offset, v) {
437                 warn!("Failed to write to PL011 device: {}", e);
438             }
439         } else {
440             warn!(
441                 "Invalid PL011 write: offset {}, data length {}",
442                 offset,
443                 data.len()
444             );
445         }
446 
447         None
448     }
449 }
450 
451 impl Snapshottable for Pl011 {
452     fn id(&self) -> String {
453         self.id.clone()
454     }
455 
456     fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
457         Snapshot::new_from_versioned_state(&self.state())
458     }
459 }
460 
461 impl Pausable for Pl011 {}
462 impl Transportable for Pl011 {}
463 impl Migratable for Pl011 {}
464 
465 #[cfg(test)]
466 mod tests {
467     use super::*;
468     use std::io;
469     use std::sync::{Arc, Mutex};
470     use vm_device::interrupt::{InterruptIndex, InterruptSourceConfig};
471     use vmm_sys_util::eventfd::EventFd;
472 
473     const SERIAL_NAME: &str = "serial";
474 
475     struct TestInterrupt {
476         event_fd: EventFd,
477     }
478 
479     impl InterruptSourceGroup for TestInterrupt {
480         fn trigger(&self, _index: InterruptIndex) -> result::Result<(), std::io::Error> {
481             self.event_fd.write(1)
482         }
483         fn update(
484             &self,
485             _index: InterruptIndex,
486             _config: InterruptSourceConfig,
487             _masked: bool,
488         ) -> result::Result<(), std::io::Error> {
489             Ok(())
490         }
491         fn notifier(&self, _index: InterruptIndex) -> Option<EventFd> {
492             Some(self.event_fd.try_clone().unwrap())
493         }
494     }
495 
496     impl TestInterrupt {
497         fn new(event_fd: EventFd) -> Self {
498             TestInterrupt { event_fd }
499         }
500     }
501 
502     #[derive(Clone)]
503     struct SharedBuffer {
504         buf: Arc<Mutex<Vec<u8>>>,
505     }
506 
507     impl SharedBuffer {
508         fn new() -> SharedBuffer {
509             SharedBuffer {
510                 buf: Arc::new(Mutex::new(Vec::new())),
511             }
512         }
513     }
514 
515     impl io::Write for SharedBuffer {
516         fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
517             self.buf.lock().unwrap().write(buf)
518         }
519         fn flush(&mut self) -> io::Result<()> {
520             self.buf.lock().unwrap().flush()
521         }
522     }
523 
524     #[test]
525     fn pl011_output() {
526         let intr_evt = EventFd::new(0).unwrap();
527         let pl011_out = SharedBuffer::new();
528         let mut pl011 = Pl011::new(
529             String::from(SERIAL_NAME),
530             Arc::new(TestInterrupt::new(intr_evt.try_clone().unwrap())),
531             Some(Box::new(pl011_out.clone())),
532             Instant::now(),
533             None,
534         );
535 
536         pl011.write(0, UARTDR, &[b'x', b'y']);
537         pl011.write(0, UARTDR, &[b'a']);
538         pl011.write(0, UARTDR, &[b'b']);
539         pl011.write(0, UARTDR, &[b'c']);
540         assert_eq!(
541             pl011_out.buf.lock().unwrap().as_slice(),
542             &[b'x', b'a', b'b', b'c']
543         );
544     }
545 
546     #[test]
547     fn pl011_input() {
548         let intr_evt = EventFd::new(0).unwrap();
549         let pl011_out = SharedBuffer::new();
550         let mut pl011 = Pl011::new(
551             String::from(SERIAL_NAME),
552             Arc::new(TestInterrupt::new(intr_evt.try_clone().unwrap())),
553             Some(Box::new(pl011_out)),
554             Instant::now(),
555             None,
556         );
557 
558         // write 1 to the interrupt event fd, so that read doesn't block in case the event fd
559         // counter doesn't change (for 0 it blocks)
560         assert!(intr_evt.write(1).is_ok());
561         pl011.queue_input_bytes(&[b'a', b'b', b'c']).unwrap();
562 
563         assert_eq!(intr_evt.read().unwrap(), 2);
564 
565         let mut data = [0u8];
566         pl011.read(0, UARTDR, &mut data);
567         assert_eq!(data[0], b'a');
568         pl011.read(0, UARTDR, &mut data);
569         assert_eq!(data[0], b'b');
570         pl011.read(0, UARTDR, &mut data);
571         assert_eq!(data[0], b'c');
572     }
573 }
574