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