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