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