serial_pl011/
lib.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Emulator for PL011 serial UART.
5//!
6//! This device does not fully implement the PL011 UART defined by ARM (e.g., it
7//! is missing DMA support), and Linux interprets it as an SBSA-compatible UART
8//! when it is enumerated by ACPI (even when we use ARM's PL011 ACPI CID). SBSA
9//! only defines a subset of the UART registers, leaving the rest as vendor
10//! specified.
11//!
12//! If you extend this emulator, do so only to make it closer to a real PL011;
13//! if you want to add other vendor-specific behavior, do it in a separate
14//! wrapping emulator.
15
16#![forbid(unsafe_code)]
17
18pub mod resolver;
19mod spec;
20
21use self::spec::ControlRegister;
22use self::spec::DmaControlRegister;
23use self::spec::FIFO_SIZE;
24use self::spec::FifoLevelSelect;
25use self::spec::FractionalBaudRateRegister;
26use self::spec::InterruptFifoLevelSelectRegister;
27use self::spec::InterruptRegister;
28use self::spec::LineControlRegister;
29use self::spec::REGISTERS_SIZE;
30use self::spec::Register;
31use self::spec::UARTPCELL_ID;
32use self::spec::UARTPERIPH_ID;
33use chipset_device::ChipsetDevice;
34use chipset_device::io::IoError;
35use chipset_device::io::IoResult;
36use chipset_device::mmio::MmioIntercept;
37use chipset_device::poll_device::PollDevice;
38use futures::AsyncRead;
39use futures::AsyncWrite;
40use inspect::Inspect;
41use inspect::InspectMut;
42use inspect_counters::Counter;
43use serial_core::SerialIo;
44use std::collections::VecDeque;
45use std::io::ErrorKind;
46use std::ops::RangeInclusive;
47use std::pin::Pin;
48use std::task::Context;
49use std::task::Poll;
50use std::task::Waker;
51use std::task::ready;
52use thiserror::Error;
53use vmcore::device_state::ChangeDeviceState;
54use vmcore::line_interrupt::LineInterrupt;
55
56/// A PL011 serial port emulator.
57#[derive(InspectMut)]
58pub struct SerialPl011 {
59    // Fixed configuration
60    #[inspect(skip)]
61    debug_name: String,
62    #[inspect(skip)]
63    mmio_region: (&'static str, RangeInclusive<u64>),
64    /// Don't transmit until the guest sets RTS. This exists here for symmetry
65    /// with the 16550 emulator, but it's not useful because this device is
66    /// enumerated as an SBSA UART, which does not support the RTS bit (a full
67    /// PL011 would).
68    wait_for_rts: bool,
69
70    // Runtime glue
71    interrupt: LineInterrupt,
72    #[inspect(mut)]
73    io: Box<dyn SerialIo>,
74
75    // Runtime book-keeping
76    state: State,
77    #[inspect(skip)]
78    rx_waker: Option<Waker>,
79    #[inspect(skip)]
80    tx_waker: Option<Waker>,
81    stats: SerialStats,
82}
83
84#[derive(Inspect, Default)]
85struct SerialStats {
86    rx_bytes: Counter,
87    tx_bytes: Counter,
88    rx_dropped: Counter,
89    tx_dropped: Counter,
90}
91
92#[derive(Inspect)]
93struct State {
94    #[inspect(with = "VecDeque::len")]
95    tx_buffer: VecDeque<u8>,
96    #[inspect(with = "VecDeque::len")]
97    rx_buffer: VecDeque<u8>,
98    rx_overrun: bool,
99    connected: bool,
100    ilpr: u8,                               // UARTILPR
101    ibrd: u16,                              // UARTIBRD
102    fbrd: FractionalBaudRateRegister,       // UARTFBRD
103    lcr: LineControlRegister,               // UARTLCR_H: u8,
104    cr: ControlRegister,                    // UARTCR: u16,
105    ifls: InterruptFifoLevelSelectRegister, // UARTIFLS: u16
106    imsc: InterruptRegister,                // UARTIMSC
107    ris: InterruptRegister, // UARTRIS: 16 holds currently asserted interrupts, only to be updated by UpdateInterrupts and writes to UARTCIR
108    dmacr: DmaControlRegister, // UARTDMACR
109
110    // Updating UARTIBRD or UARTFBRD requires a write to UARTLCR_H.
111    // Thus, we need to store if we've seen a different value incase we ever see a UARTLCR_H write.
112    new_ibrd: u16,
113    new_fbrd: FractionalBaudRateRegister,
114}
115
116// A normal FIFO has only 16 bytes, but we get greater batching with these values.
117const TX_BUFFER_MAX: usize = 256;
118const RX_BUFFER_MAX: usize = 256;
119
120/// An error returned by [`SerialPl011::new`].
121#[derive(Debug, Error)]
122pub enum ConfigurationError {
123    /// The provided base address was not aligned to the register bank width.
124    #[error("unaligned base address: {0}")]
125    UnalignedBaseAddress(u64),
126    /// The specified register with was invalid.
127    #[error("invalid register width: {0}")]
128    InvalidRegisterWidth(u8),
129}
130
131impl SerialPl011 {
132    /// Returns a new emulator instance.
133    ///
134    /// `debug_name` is used to improve tracing statements. `base` is the base
135    /// IO port and will be used for an IO region spanning 8 bytes.
136    pub fn new(
137        debug_name: String,
138        base: u64,
139        interrupt: LineInterrupt,
140        io: Box<dyn SerialIo>,
141    ) -> Result<Self, ConfigurationError> {
142        if base & (REGISTERS_SIZE - 1) != 0 {
143            return Err(ConfigurationError::UnalignedBaseAddress(base));
144        }
145
146        let mut this = Self {
147            debug_name,
148            mmio_region: ("registers", base..=base + (REGISTERS_SIZE - 1)),
149            wait_for_rts: false,
150            state: State::new(),
151            interrupt,
152            io,
153            rx_waker: None,
154            tx_waker: None,
155            stats: Default::default(),
156        };
157        if this.io.is_connected() {
158            this.state.connect();
159        }
160        this.sync();
161        Ok(this)
162    }
163
164    /// Synchronize interrupt and waker state with device state.
165    fn sync(&mut self) {
166        // Wake to poll if there are any bytes to write.
167        if !self.state.tx_buffer.is_empty() {
168            if let Some(waker) = self.tx_waker.take() {
169                waker.wake();
170            }
171        }
172
173        // Reduce wakeups by waking to poll if the rx buffer is at least half empty.
174        if self.state.should_poll_rx(self.wait_for_rts)
175            && self.state.rx_buffer.len() <= RX_BUFFER_MAX / 2
176        {
177            if let Some(waker) = self.rx_waker.take() {
178                waker.wake();
179            }
180        }
181
182        // Synchronize the receive timeout interrupt. In hardware, this would
183        // only raise after 32 bits worth of clock have expired and there is
184        // data in the RX FIFO. But that's too hard, so just treat the clock as
185        // expiring constantly.
186        //
187        // This means the guest can't really clear this interrupt as long as
188        // there is data in the FIFO.
189        self.state.ris.set_rt(!self.state.rx_buffer.is_empty());
190
191        // Synchronize the interrupt output.
192        self.interrupt.set_level(self.state.pending_interrupt());
193    }
194
195    fn poll_tx(&mut self, cx: &mut Context<'_>) -> Poll<()> {
196        while !self.state.tx_buffer.is_empty() {
197            if !self.state.connected {
198                // The backend is disconnected, so drop everything in the FIFO.
199                self.stats.tx_dropped.add(self.state.tx_buffer.len() as u64);
200                if self.state.tx_buffer.len() > self.state.tx_fifo_trigger() {
201                    self.state.ris.set_tx(true);
202                }
203                self.state.tx_buffer.clear();
204                break;
205            }
206            let (buf, _) = self.state.tx_buffer.as_slices();
207            let old_len = self.state.tx_buffer.len();
208            match ready!(Pin::new(&mut self.io).poll_write(cx, buf)) {
209                Ok(n) => {
210                    assert_ne!(n, 0);
211                    self.state.tx_buffer.drain(..n);
212                    self.stats.tx_bytes.add(n as u64);
213                }
214                Err(err) if err.kind() == ErrorKind::BrokenPipe => {
215                    tracing::info!(
216                        port = self.debug_name,
217                        "serial output broken pipe, disconnecting"
218                    );
219                    self.state.disconnect();
220                }
221                Err(err) => {
222                    tracelimit::error_ratelimited!(
223                        port = self.debug_name,
224                        len = buf.len(),
225                        error = &err as &dyn std::error::Error,
226                        "serial write failed, dropping data"
227                    );
228                    self.stats.tx_dropped.add(buf.len() as u64);
229                    self.state.tx_buffer.drain(..buf.len());
230                }
231            }
232            let tx_fifo_trigger = self.state.tx_fifo_trigger();
233            if old_len > tx_fifo_trigger && self.state.tx_buffer.len() <= tx_fifo_trigger {
234                self.state.ris.set_tx(true);
235            }
236        }
237        // Wait for more bytes to write.
238        self.tx_waker = Some(cx.waker().clone());
239        Poll::Pending
240    }
241
242    fn poll_rx(&mut self, cx: &mut Context<'_>) -> Poll<()> {
243        let mut buf = [0; RX_BUFFER_MAX];
244        loop {
245            if !self.state.connected {
246                // Wait for reconnect.
247                if let Err(err) = ready!(self.io.poll_connect(cx)) {
248                    tracing::info!(
249                        port = self.debug_name,
250                        error = &err as &dyn std::error::Error,
251                        "serial backend failure"
252                    );
253                    break Poll::Ready(());
254                }
255                tracing::trace!(port = self.debug_name, "serial connected");
256                self.state.connect();
257            }
258            if !self.state.should_poll_rx(self.wait_for_rts) {
259                // Wait for buffer space to read into, or to leave loopback mode.
260                self.rx_waker = Some(cx.waker().clone());
261                if let Err(err) = ready!(self.io.poll_disconnect(cx)) {
262                    tracing::info!(
263                        port = self.debug_name,
264                        error = &err as &dyn std::error::Error,
265                        "serial backend failure"
266                    );
267                    break Poll::Ready(());
268                }
269                tracing::trace!(port = self.debug_name, "serial disconnected");
270                self.state.disconnect();
271                continue;
272            }
273            let avail_space = RX_BUFFER_MAX - self.state.rx_buffer.len();
274            let buf = &mut buf[..avail_space];
275            match ready!(Pin::new(&mut self.io).poll_read(cx, buf)) {
276                Ok(0) => {
277                    tracing::trace!(port = self.debug_name, "serial disconnected");
278                    self.state.disconnect();
279                }
280                Ok(n) => {
281                    let rx_fifo_trigger = self.state.rx_fifo_trigger();
282                    if self.state.rx_buffer.len() < rx_fifo_trigger
283                        && self.state.rx_buffer.len() + n >= rx_fifo_trigger
284                    {
285                        self.state.ris.set_rx(true);
286                    }
287                    self.state.rx_buffer.extend(&buf[..n]);
288                    self.stats.rx_bytes.add(n as u64);
289                }
290                Err(err) => {
291                    tracing::error!(
292                        port = self.debug_name,
293                        error = &err as &dyn std::error::Error,
294                        "failed to read serial input, disconnecting"
295                    );
296                    self.state.disconnect();
297                    break Poll::Ready(());
298                }
299            }
300        }
301    }
302
303    fn register(&self, addr: u64) -> Result<Register, IoError> {
304        // All registers are 32 bits wide, and the SBSA spec requires aligned access.
305        if addr & 3 != 0 {
306            return Err(IoError::UnalignedAccess);
307        }
308        Ok(Register((addr & (REGISTERS_SIZE - 1)) as u16))
309    }
310
311    fn read(&mut self, addr: u64, data: &mut [u8]) -> IoResult {
312        let register = match self.register(addr) {
313            Err(e) => return IoResult::Err(e),
314            Ok(r) => r,
315        };
316
317        data.fill(0);
318        let val: u16 = match register {
319            Register::UARTDR => self.state.read_dr().into(),
320            Register::UARTRSR => 0, // Status flags we don't care about, return zeros.
321            Register::UARTFR => self.state.read_fr(),
322            Register::UARTILPR => self.state.ilpr as u16,
323            Register::UARTIBRD => self.state.ibrd,
324            Register::UARTFBRD => u8::from(self.state.fbrd) as u16,
325            Register::UARTLCR_H => u8::from(self.state.lcr) as u16,
326            Register::UARTCR => u16::from(self.state.cr),
327            Register::UARTIFLS => u16::from(self.state.ifls),
328            Register::UARTIMSC => u16::from(self.state.imsc),
329            Register::UARTRIS => u16::from(self.state.ris),
330            Register::UARTMIS => u16::from(self.state.ris) & u16::from(self.state.imsc),
331            Register::UARTDMACR => u16::from(self.state.dmacr),
332            Register::UARTPERIPHID0 => UARTPERIPH_ID[0],
333            Register::UARTPERIPHID1 => UARTPERIPH_ID[1],
334            Register::UARTPERIPHID2 => UARTPERIPH_ID[2],
335            Register::UARTPERIPHID3 => UARTPERIPH_ID[3],
336            Register::UARTPCELLID0 => UARTPCELL_ID[0],
337            Register::UARTPCELLID1 => UARTPCELL_ID[1],
338            Register::UARTPCELLID2 => UARTPCELL_ID[2],
339            Register::UARTPCELLID3 => UARTPCELL_ID[3],
340            _ => return IoResult::Err(IoError::InvalidRegister),
341        };
342
343        // The SBSA spec only requires the device to support 8-bit reads on some
344        // registers and leaves it implementation defined on others. Allow 8-bit
345        // reads on all registers for simplicity.
346        data[0] = val.to_le_bytes()[0];
347        if data.len() > 1 {
348            data[1] = val.to_le_bytes()[1];
349        }
350
351        self.sync();
352        IoResult::Ok
353    }
354
355    fn write(&mut self, addr: u64, data: &[u8]) -> IoResult {
356        let register = match self.register(addr) {
357            Err(e) => return IoResult::Err(e),
358            Ok(r) => r,
359        };
360
361        tracing::trace!(?register, ?data, "serial write");
362
363        // Registers that allow 8-bit access.
364        match register {
365            Register::UARTDR => self.state.write_dr(&mut self.stats, data[0]),
366            Register::UARTECR => {}
367            Register::UARTILPR => self.state.ilpr = data[0],
368            Register::UARTFBRD => self.state.write_fbrd(data[0]),
369            Register::UARTLCR_H => self.state.write_lcrh(&mut self.stats, data[0]),
370            _ => {
371                // 16-bit registers.
372                let Some(data) = data.get(..2) else {
373                    return IoResult::Err(IoError::InvalidAccessSize);
374                };
375                let data16 = u16::from_le_bytes(data.try_into().unwrap());
376                match register {
377                    Register::UARTIBRD => self.state.new_ibrd = data16,
378                    Register::UARTCR => self.state.write_cr(data16),
379                    Register::UARTIFLS => self.state.write_ifls(data16),
380                    Register::UARTIMSC => self.state.write_imsc(data16),
381                    Register::UARTICR => self.state.write_icr(data16),
382                    Register::UARTDMACR => self.state.write_dmacr(data16),
383                    _ => return IoResult::Err(IoError::InvalidRegister),
384                };
385            }
386        }
387        self.sync();
388        IoResult::Ok
389    }
390}
391
392impl ChangeDeviceState for SerialPl011 {
393    fn start(&mut self) {}
394
395    async fn stop(&mut self) {}
396
397    async fn reset(&mut self) {
398        self.state = State::new();
399        self.state.connect();
400        self.sync();
401    }
402}
403
404impl ChipsetDevice for SerialPl011 {
405    fn supports_mmio(&mut self) -> Option<&mut dyn MmioIntercept> {
406        Some(self)
407    }
408
409    fn supports_poll_device(&mut self) -> Option<&mut dyn PollDevice> {
410        Some(self)
411    }
412}
413
414impl PollDevice for SerialPl011 {
415    fn poll_device(&mut self, cx: &mut Context<'_>) {
416        let _ = self.poll_tx(cx);
417        let _ = self.poll_rx(cx);
418        self.sync();
419    }
420}
421
422impl State {
423    fn new() -> Self {
424        // The initial state for this UART does not completely match the PL011
425        // specification. This is because Linux loads its SBSA-compatible UART
426        // driver instead of its PL011 driver, and the SBSA-compatible driver
427        // expects the firmware to initialize the UART.
428        //
429        // We could look at enumerating this as a true PL011 instead, but
430        // 1. It's unclear how to do this with ACPI (it's trivial with
431        //    DeviceTree).
432        // 2. There may be a compatibility concern with changing the
433        //    enumeration.
434        // 3. This is not really a full PL011 emulator anyway, since it does not
435        //    support DMA.
436        //
437        // Instead, initialize the state as defined in the SBSA. Normally
438        // firmware would do this, but we do it here.
439
440        let cr = ControlRegister::new()
441            .with_enabled(true)
442            .with_rxe(true)
443            .with_txe(true);
444
445        let lcr = LineControlRegister::new().with_enable_fifos(true);
446
447        Self {
448            tx_buffer: VecDeque::new(),
449            rx_buffer: VecDeque::new(),
450            rx_overrun: false,
451            connected: false,
452            ilpr: 0,
453            ibrd: 0,
454            fbrd: FractionalBaudRateRegister::new(),
455            lcr,
456            cr,
457            ifls: InterruptFifoLevelSelectRegister::new()
458                .with_txiflsel(FifoLevelSelect::BYTES_16.0)
459                .with_rxiflsel(FifoLevelSelect::BYTES_16.0),
460            imsc: InterruptRegister::new(),
461            ris: InterruptRegister::new(),
462            dmacr: DmaControlRegister::new(),
463            new_ibrd: 0,
464            new_fbrd: FractionalBaudRateRegister::new(),
465        }
466    }
467
468    /// Updates CR when the modem connects.
469    fn connect(&mut self) {
470        if !self.connected {
471            self.connected = true;
472            // CTS/DCD/DSR changed.
473            self.ris.set_cts(true);
474            self.ris.set_dcd(true);
475            self.ris.set_dsr(true);
476        }
477    }
478
479    /// Updates CR when the modem disconnects.
480    fn disconnect(&mut self) {
481        if self.connected {
482            self.connected = false;
483            // CTS/DCD/DSR changed.
484            self.ris.set_cts(true);
485            self.ris.set_dcd(true);
486            self.ris.set_dsr(true);
487        }
488    }
489
490    fn tx_fifo_trigger(&self) -> usize {
491        if self.lcr.enable_fifos() {
492            match FifoLevelSelect(self.ifls.txiflsel()) {
493                FifoLevelSelect::BYTES_4 => 4,   // <= 1/8 full
494                FifoLevelSelect::BYTES_8 => 8,   // <= 1/4 full
495                FifoLevelSelect::BYTES_16 => 16, // <= 1/2 full
496                FifoLevelSelect::BYTES_24 => 24, // <= 3/4 full
497                FifoLevelSelect::BYTES_28 => 28, // <= 7/8 full
498                _ => 16,                         // reserved
499            }
500        } else {
501            0
502        }
503    }
504
505    fn rx_fifo_trigger(&self) -> usize {
506        if self.lcr.enable_fifos() {
507            match FifoLevelSelect(self.ifls.rxiflsel()) {
508                FifoLevelSelect::BYTES_4 => 4,   // <= 1/8 full
509                FifoLevelSelect::BYTES_8 => 8,   // <= 1/4 full
510                FifoLevelSelect::BYTES_16 => 16, // <= 1/2 full
511                FifoLevelSelect::BYTES_24 => 24, // <= 3/4 full
512                FifoLevelSelect::BYTES_28 => 28, // <= 7/8 full
513                _ => 16,                         // reserved
514            }
515        } else {
516            1
517        }
518    }
519
520    fn fifo_size(&self) -> usize {
521        if self.lcr.enable_fifos() {
522            FIFO_SIZE
523        } else {
524            1
525        }
526    }
527
528    /// Returns whether it is time to poll the backend device for more data.
529    fn should_poll_rx(&self, wait_for_rts: bool) -> bool {
530        // Only poll if not in loopback mode, since data comes from THR in that case.
531        if self.cr.loopback() {
532            return false;
533        }
534
535        // Only poll if the backend is connected.
536        if !self.connected {
537            return false;
538        }
539
540        // If requested, only poll if the OS is requesting data. Essentially
541        // this means the backend device implements hardware flow control.
542        //
543        // Without this, any data buffered into the serial port will be lost
544        // during boot when the FIFO is cleared.
545        if wait_for_rts && (!self.cr.dtr() || !self.cr.rts()) {
546            return false;
547        }
548
549        // Only poll if there is space in the buffer.
550        self.rx_buffer.len() < RX_BUFFER_MAX
551    }
552
553    fn pending_interrupt(&mut self) -> bool {
554        u16::from(self.ris) & u16::from(self.imsc) != 0
555    }
556
557    fn read_dr(&mut self) -> u8 {
558        if self.rx_buffer.is_empty() {
559            return 0;
560        }
561
562        let rx = self.rx_buffer.pop_front().unwrap_or(0);
563        if self.rx_buffer.len() < self.rx_fifo_trigger() {
564            self.ris.set_rx(false);
565        }
566        rx
567    }
568
569    fn write_dr(&mut self, stats: &mut SerialStats, data: u8) {
570        if self.cr.loopback() {
571            // Loopback mode wires UARTTXD to UARTRXD, so just add a byte
572            // to the fifo along with updating tx state.
573            if self.cr.enabled() && self.cr.txe() {
574                if self.cr.rxe() {
575                    if self.rx_buffer.len() >= TX_BUFFER_MAX {
576                        stats
577                            .rx_dropped
578                            .add((self.rx_buffer.len() - TX_BUFFER_MAX) as u64);
579                        self.rx_buffer.truncate(TX_BUFFER_MAX);
580                        self.rx_overrun = true;
581                        self.ris.set_oe(true);
582                    }
583
584                    self.rx_buffer.push_back(data);
585                    if self.rx_buffer.len() == self.rx_fifo_trigger() {
586                        self.ris.set_rx(true);
587                    }
588                }
589            }
590        } else {
591            if self.tx_buffer.len() >= TX_BUFFER_MAX {
592                // The FIFO is full. Real hardware drops the newest byte in the
593                // FIFO, not the oldest one.
594                tracing::debug!("tx fifo overrun, dropping output data");
595                stats
596                    .tx_dropped
597                    .add((self.tx_buffer.len() - (TX_BUFFER_MAX - 1)) as u64);
598                self.tx_buffer.truncate(TX_BUFFER_MAX - 1);
599            }
600            self.tx_buffer.push_back(data);
601
602            if self.tx_buffer.len() > self.tx_fifo_trigger() {
603                self.ris.set_tx(false);
604            }
605        }
606    }
607
608    fn write_fbrd(&mut self, data: u8) {
609        self.new_fbrd = FractionalBaudRateRegister::from(data).clear_reserved();
610    }
611
612    fn write_lcrh(&mut self, stats: &mut SerialStats, data: u8) {
613        // This register should not be written to when the UART is enabled.
614        if self.cr.enabled() {
615            return;
616        }
617
618        if self.new_ibrd != self.ibrd || u8::from(self.new_fbrd) != u8::from(self.fbrd) {
619            self.ibrd = self.new_ibrd;
620            self.fbrd = self.new_fbrd;
621        }
622
623        let lcr = LineControlRegister::from(data);
624        if self.lcr.enable_fifos() && !lcr.enable_fifos() {
625            // Fifo went from enabled -> disabled, clear all fifos and update status regs.
626            // Additionally, since this can only happen when the UART is disabled, there's no need to update interrupts.
627            stats.rx_dropped.add(self.rx_buffer.len() as u64);
628            self.rx_buffer.clear();
629
630            stats.tx_dropped.add(self.tx_buffer.len() as u64);
631            self.tx_buffer.clear();
632        }
633
634        self.lcr = lcr;
635    }
636
637    fn write_cr(&mut self, data: u16) {
638        self.cr = ControlRegister::from(data).clear_reserved();
639    }
640
641    fn write_ifls(&mut self, data: u16) {
642        self.ifls = InterruptFifoLevelSelectRegister::from(data).clear_reserved();
643    }
644
645    fn write_imsc(&mut self, data: u16) {
646        self.imsc = InterruptRegister::from(data).clear_reserved();
647    }
648
649    fn write_icr(&mut self, data: u16) {
650        self.ris = InterruptRegister::from(u16::from(self.ris) & !data);
651    }
652
653    fn write_dmacr(&mut self, data: u16) {
654        self.dmacr = DmaControlRegister::from(data).clear_reserved()
655    }
656
657    fn read_fr(&self) -> u16 {
658        let fifo_size = self.fifo_size();
659        let fr = spec::FlagRegister::new()
660            .with_cts(self.connected)
661            .with_dcd(self.connected)
662            .with_dsr(self.connected)
663            .with_busy(!self.tx_buffer.is_empty())
664            .with_rxfe(self.rx_buffer.is_empty())
665            .with_txff(self.tx_buffer.len() >= fifo_size)
666            .with_rxff(self.rx_buffer.len() >= fifo_size)
667            .with_txfe(self.tx_buffer.is_empty());
668
669        fr.into()
670    }
671}
672
673impl MmioIntercept for SerialPl011 {
674    fn mmio_read(&mut self, addr: u64, data: &mut [u8]) -> IoResult {
675        self.read(addr, data)
676    }
677
678    fn mmio_write(&mut self, addr: u64, data: &[u8]) -> IoResult {
679        self.write(addr, data)
680    }
681
682    fn get_static_regions(&mut self) -> &[(&str, RangeInclusive<u64>)] {
683        std::slice::from_ref(&self.mmio_region)
684    }
685}
686
687mod save_restore {
688    use crate::SerialPl011;
689    use crate::State;
690    use vmcore::save_restore::RestoreError;
691    use vmcore::save_restore::SaveError;
692    use vmcore::save_restore::SaveRestore;
693
694    mod state {
695        use mesh::payload::Protobuf;
696        use vmcore::save_restore::SavedStateRoot;
697
698        #[derive(Protobuf, SavedStateRoot)]
699        #[mesh(package = "serial.PL011")]
700        pub struct SavedState {
701            #[mesh(1)]
702            pub(super) tx_buffer: Vec<u8>,
703            #[mesh(2)]
704            pub(super) rx_buffer: Vec<u8>,
705            #[mesh(3)]
706            pub(super) rx_overrun: bool,
707            #[mesh(4)]
708            pub(super) connected: bool,
709            #[mesh(5)]
710            pub(super) ilpr: u8,
711            #[mesh(6)]
712            pub(super) ibrd: u16,
713            #[mesh(7)]
714            pub(super) fbrd: u8,
715            #[mesh(8)]
716            pub(super) lcr: u8,
717            #[mesh(9)]
718            pub(super) cr: u16,
719            #[mesh(10)]
720            pub(super) ifls: u16,
721            #[mesh(11)]
722            pub(super) imsc: u16,
723            #[mesh(12)]
724            pub(super) ris: u16,
725            #[mesh(13)]
726            pub(super) dmacr: u16,
727            #[mesh(14)]
728            pub(super) new_ibrd: u16,
729            #[mesh(15)]
730            pub(super) new_fbrd: u8,
731        }
732    }
733
734    impl SaveRestore for SerialPl011 {
735        type SavedState = state::SavedState;
736
737        fn save(&mut self) -> Result<Self::SavedState, SaveError> {
738            let State {
739                ref tx_buffer,
740                ref rx_buffer,
741                rx_overrun,
742                connected,
743                ilpr,
744                ibrd,
745                fbrd,
746                lcr,
747                cr,
748                ifls,
749                imsc,
750                ris,
751                dmacr,
752                new_ibrd,
753                new_fbrd,
754            } = self.state;
755            Ok(state::SavedState {
756                tx_buffer: tx_buffer.clone().into(),
757                rx_buffer: rx_buffer.clone().into(),
758                rx_overrun,
759                connected,
760                ilpr,
761                ibrd,
762                fbrd: fbrd.into(),
763                lcr: lcr.into(),
764                cr: cr.into(),
765                ifls: ifls.into(),
766                imsc: imsc.into(),
767                ris: ris.into(),
768                dmacr: dmacr.into(),
769                new_ibrd,
770                new_fbrd: new_fbrd.into(),
771            })
772        }
773
774        fn restore(&mut self, state: Self::SavedState) -> Result<(), RestoreError> {
775            let state::SavedState {
776                tx_buffer,
777                rx_buffer,
778                rx_overrun,
779                connected,
780                ilpr,
781                ibrd,
782                fbrd,
783                lcr,
784                cr,
785                ifls,
786                imsc,
787                ris,
788                dmacr,
789                new_ibrd,
790                new_fbrd,
791            } = state;
792            self.state = State {
793                tx_buffer: tx_buffer.into(),
794                rx_buffer: rx_buffer.into(),
795                rx_overrun,
796                connected,
797                ilpr,
798                ibrd,
799                fbrd: fbrd.into(),
800                lcr: lcr.into(),
801                cr: cr.into(),
802                ifls: ifls.into(),
803                imsc: imsc.into(),
804                ris: ris.into(),
805                dmacr: dmacr.into(),
806                new_ibrd,
807                new_fbrd: new_fbrd.into(),
808            };
809            if self.io.is_connected() {
810                self.state.connect();
811            } else {
812                self.state.disconnect();
813            }
814            self.sync();
815            Ok(())
816        }
817    }
818}
819
820#[cfg(test)]
821mod tests {
822    use super::*;
823    use chipset_device::io::IoError;
824    use chipset_device::io::IoResult;
825    use chipset_device::mmio::MmioIntercept;
826    use futures::AsyncRead;
827    use futures::AsyncWrite;
828    use inspect::InspectMut;
829    use pal_async::async_test;
830    use serial_core::SerialIo;
831    use std::future::poll_fn;
832    use std::io;
833    use std::pin::Pin;
834    use std::task::Context;
835    use std::task::Poll;
836    use vmcore::line_interrupt::LineInterrupt;
837
838    const PL011_SERIAL0_BASE: u64 = 0xEFFEC000;
839
840    const UARTCR_TXE: u16 = 0x0100;
841    const UARTCR_RXE: u16 = 0x0200;
842    const UARTCR_UARTEN: u16 = 0x0001;
843
844    const UARTLCR_H_FIFO_ENABLE: u16 = 0x0010;
845    const UARTLCR_H_8BITS: u16 = 0x0060;
846
847    // This is a "loopback" kind of io, where a write to the serial port will appear in the read queue
848    #[derive(InspectMut)]
849    pub struct SerialIoMock {
850        data: Vec<u8>,
851    }
852
853    impl SerialIo for SerialIoMock {
854        fn is_connected(&self) -> bool {
855            true
856        }
857
858        fn poll_connect(&mut self, _cx: &mut Context<'_>) -> Poll<io::Result<()>> {
859            Poll::Ready(Ok(()))
860        }
861
862        fn poll_disconnect(&mut self, _cx: &mut Context<'_>) -> Poll<io::Result<()>> {
863            Poll::Ready(Ok(()))
864        }
865    }
866
867    impl AsyncRead for SerialIoMock {
868        fn poll_read(
869            mut self: Pin<&mut Self>,
870            _cx: &mut Context<'_>,
871            buf: &mut [u8],
872        ) -> Poll<io::Result<usize>> {
873            if self.data.is_empty() {
874                return Poll::Ready(Err(ErrorKind::ConnectionAborted.into()));
875            }
876            let n = buf.len().min(self.data.len());
877            for (s, d) in self.data.drain(..n).zip(buf) {
878                *d = s;
879            }
880            Poll::Ready(Ok(n))
881        }
882    }
883
884    impl AsyncWrite for SerialIoMock {
885        fn poll_write(
886            mut self: Pin<&mut Self>,
887            _cx: &mut Context<'_>,
888            buf: &[u8],
889        ) -> Poll<io::Result<usize>> {
890            let buf = &buf[..buf.len().min(FIFO_SIZE)];
891            self.data.extend_from_slice(buf);
892            Poll::Ready(Ok(buf.len()))
893        }
894
895        fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<()>> {
896            Poll::Ready(Ok(()))
897        }
898
899        fn poll_close(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<()>> {
900            Poll::Ready(Ok(()))
901        }
902    }
903
904    impl SerialIoMock {
905        pub fn new() -> Self {
906            Self { data: Vec::new() }
907        }
908    }
909
910    #[test]
911    fn test_read() {
912        let serial_io = SerialIoMock::new();
913        let mut serial = SerialPl011::new(
914            "com1".to_string(),
915            PL011_SERIAL0_BASE,
916            LineInterrupt::detached(),
917            Box::new(serial_io),
918        )
919        .unwrap();
920
921        let mut data = vec![0; 1];
922        serial.mmio_read(0, &mut data).unwrap();
923
924        let mut data = vec![0; 2];
925        serial.mmio_read(0, &mut data).unwrap();
926
927        let mut data = vec![0; 4];
928        serial.mmio_read(0, &mut data).unwrap();
929
930        assert!(matches!(
931            serial.mmio_read(1, &mut data),
932            IoResult::Err(IoError::UnalignedAccess)
933        ));
934        assert!(matches!(
935            serial.mmio_read(2, &mut data),
936            IoResult::Err(IoError::UnalignedAccess)
937        ));
938        assert!(matches!(
939            serial.mmio_read(3, &mut data),
940            IoResult::Err(IoError::UnalignedAccess)
941        ));
942
943        serial
944            .mmio_read(Register::UARTDR.0 as u64, &mut data)
945            .unwrap();
946        serial
947            .mmio_read(Register::UARTRSR.0 as u64, &mut data)
948            .unwrap();
949        serial
950            .mmio_read(Register::UARTECR.0 as u64, &mut data)
951            .unwrap();
952        serial
953            .mmio_read(Register::UARTFR.0 as u64, &mut data)
954            .unwrap();
955        serial
956            .mmio_read(Register::UARTILPR.0 as u64, &mut data)
957            .unwrap();
958        serial
959            .mmio_read(Register::UARTIBRD.0 as u64, &mut data)
960            .unwrap();
961        serial
962            .mmio_read(Register::UARTFBRD.0 as u64, &mut data)
963            .unwrap();
964        serial
965            .mmio_read(Register::UARTLCR_H.0 as u64, &mut data)
966            .unwrap();
967        serial
968            .mmio_read(Register::UARTCR.0 as u64, &mut data)
969            .unwrap();
970        serial
971            .mmio_read(Register::UARTIFLS.0 as u64, &mut data)
972            .unwrap();
973        serial
974            .mmio_read(Register::UARTIMSC.0 as u64, &mut data)
975            .unwrap();
976        serial
977            .mmio_read(Register::UARTRIS.0 as u64, &mut data)
978            .unwrap();
979        serial
980            .mmio_read(Register::UARTMIS.0 as u64, &mut data)
981            .unwrap();
982        assert!(matches!(
983            serial.mmio_read(Register::UARTICR.0 as u64, &mut data),
984            IoResult::Err(IoError::InvalidRegister)
985        ));
986        serial
987            .mmio_read(Register::UARTDMACR.0 as u64, &mut data)
988            .unwrap();
989
990        serial
991            .mmio_read(Register::UARTPERIPHID0.0 as u64, &mut data)
992            .unwrap();
993        serial
994            .mmio_read(Register::UARTPERIPHID1.0 as u64, &mut data)
995            .unwrap();
996        serial
997            .mmio_read(Register::UARTPERIPHID2.0 as u64, &mut data)
998            .unwrap();
999        serial
1000            .mmio_read(Register::UARTPERIPHID3.0 as u64, &mut data)
1001            .unwrap();
1002        serial
1003            .mmio_read(Register::UARTPCELLID0.0 as u64, &mut data)
1004            .unwrap();
1005        serial
1006            .mmio_read(Register::UARTPCELLID1.0 as u64, &mut data)
1007            .unwrap();
1008        serial
1009            .mmio_read(Register::UARTPCELLID2.0 as u64, &mut data)
1010            .unwrap();
1011        serial
1012            .mmio_read(Register::UARTPCELLID3.0 as u64, &mut data)
1013            .unwrap();
1014    }
1015
1016    #[test]
1017    fn test_write() {
1018        let serial_io = SerialIoMock::new();
1019        let mut serial = SerialPl011::new(
1020            "com1".to_string(),
1021            PL011_SERIAL0_BASE,
1022            LineInterrupt::detached(),
1023            Box::new(serial_io),
1024        )
1025        .unwrap();
1026
1027        let data = vec![0; 1];
1028        assert!(matches!(
1029            serial.mmio_write(Register::UARTIBRD.0.into(), &data),
1030            IoResult::Err(IoError::InvalidAccessSize)
1031        ));
1032
1033        let data = vec![0; 2];
1034        serial.mmio_write(0, &data).unwrap();
1035
1036        let data = vec![0; 3];
1037        serial.mmio_write(0, &data).unwrap();
1038
1039        let data = vec![0; 4];
1040        serial.mmio_write(0, &data).unwrap();
1041
1042        let data = vec![0; 5];
1043        serial.mmio_write(0, &data).unwrap();
1044
1045        assert!(matches!(
1046            serial.mmio_write(1, &data),
1047            IoResult::Err(IoError::UnalignedAccess)
1048        ));
1049        assert!(matches!(
1050            serial.mmio_write(2, &data),
1051            IoResult::Err(IoError::UnalignedAccess)
1052        ));
1053        assert!(matches!(
1054            serial.mmio_write(3, &data),
1055            IoResult::Err(IoError::UnalignedAccess)
1056        ));
1057
1058        serial.mmio_write(Register::UARTDR.0 as u64, &data).unwrap();
1059        serial
1060            .mmio_write(Register::UARTRSR.0 as u64, &data)
1061            .unwrap();
1062        serial
1063            .mmio_write(Register::UARTECR.0 as u64, &data)
1064            .unwrap();
1065        assert!(matches!(
1066            serial.mmio_write(Register::UARTFR.0 as u64, &data),
1067            IoResult::Err(IoError::InvalidRegister)
1068        ));
1069        serial
1070            .mmio_write(Register::UARTILPR.0 as u64, &data)
1071            .unwrap();
1072        serial
1073            .mmio_write(Register::UARTIBRD.0 as u64, &data)
1074            .unwrap();
1075        serial
1076            .mmio_write(Register::UARTFBRD.0 as u64, &data)
1077            .unwrap();
1078        serial
1079            .mmio_write(Register::UARTLCR_H.0 as u64, &data)
1080            .unwrap();
1081        serial.mmio_write(Register::UARTCR.0 as u64, &data).unwrap();
1082        serial
1083            .mmio_write(Register::UARTIFLS.0 as u64, &data)
1084            .unwrap();
1085        serial
1086            .mmio_write(Register::UARTIMSC.0 as u64, &data)
1087            .unwrap();
1088        assert!(matches!(
1089            serial.mmio_write(Register::UARTRIS.0 as u64, &data),
1090            IoResult::Err(IoError::InvalidRegister)
1091        ));
1092        assert!(matches!(
1093            serial.mmio_write(Register::UARTMIS.0 as u64, &data),
1094            IoResult::Err(IoError::InvalidRegister)
1095        ));
1096        serial
1097            .mmio_write(Register::UARTICR.0 as u64, &data)
1098            .unwrap();
1099        serial
1100            .mmio_write(Register::UARTDMACR.0 as u64, &data)
1101            .unwrap();
1102
1103        assert!(matches!(
1104            serial.mmio_write(Register::UARTPERIPHID0.0 as u64, &data),
1105            IoResult::Err(IoError::InvalidRegister)
1106        ));
1107        assert!(matches!(
1108            serial.mmio_write(Register::UARTPERIPHID1.0 as u64, &data),
1109            IoResult::Err(IoError::InvalidRegister)
1110        ));
1111        assert!(matches!(
1112            serial.mmio_write(Register::UARTPERIPHID2.0 as u64, &data),
1113            IoResult::Err(IoError::InvalidRegister)
1114        ));
1115        assert!(matches!(
1116            serial.mmio_write(Register::UARTPERIPHID3.0 as u64, &data),
1117            IoResult::Err(IoError::InvalidRegister)
1118        ));
1119        assert!(matches!(
1120            serial.mmio_write(Register::UARTPCELLID0.0 as u64, &data),
1121            IoResult::Err(IoError::InvalidRegister)
1122        ));
1123        assert!(matches!(
1124            serial.mmio_write(Register::UARTPCELLID1.0 as u64, &data),
1125            IoResult::Err(IoError::InvalidRegister)
1126        ));
1127        assert!(matches!(
1128            serial.mmio_write(Register::UARTPCELLID2.0 as u64, &data),
1129            IoResult::Err(IoError::InvalidRegister)
1130        ));
1131        assert!(matches!(
1132            serial.mmio_write(Register::UARTPCELLID3.0 as u64, &data),
1133            IoResult::Err(IoError::InvalidRegister)
1134        ));
1135    }
1136
1137    fn read(serial: &mut SerialPl011, r: Register) -> u16 {
1138        let mut data = vec![0; 2];
1139        serial.mmio_read(r.0 as u64, &mut data).unwrap();
1140        u16::from_ne_bytes(data[..2].try_into().unwrap())
1141    }
1142
1143    fn write(serial: &mut SerialPl011, r: Register, val: u16) {
1144        let mut data = vec![0; 2];
1145        data[..2].copy_from_slice(&val.to_ne_bytes());
1146        serial.mmio_write(r.0 as u64, &data).unwrap();
1147    }
1148
1149    #[test]
1150    fn test_init() {
1151        let serial_io = SerialIoMock::new();
1152        let mut serial = SerialPl011::new(
1153            "com1".to_string(),
1154            PL011_SERIAL0_BASE,
1155            LineInterrupt::detached(),
1156            Box::new(serial_io),
1157        )
1158        .unwrap();
1159
1160        assert_eq!(read(&mut serial, Register::UARTPERIPHID0), UARTPERIPH_ID[0]);
1161        assert_eq!(read(&mut serial, Register::UARTPERIPHID1), UARTPERIPH_ID[1]);
1162        assert_eq!(read(&mut serial, Register::UARTPERIPHID2), UARTPERIPH_ID[2]);
1163        assert_eq!(read(&mut serial, Register::UARTPERIPHID3), UARTPERIPH_ID[3]);
1164        assert_eq!(read(&mut serial, Register::UARTPCELLID0), UARTPCELL_ID[0]);
1165        assert_eq!(read(&mut serial, Register::UARTPCELLID1), UARTPCELL_ID[1]);
1166        assert_eq!(read(&mut serial, Register::UARTPCELLID2), UARTPCELL_ID[2]);
1167        assert_eq!(read(&mut serial, Register::UARTPCELLID3), UARTPCELL_ID[3]);
1168
1169        // Mask interrupts
1170        write(&mut serial, Register::UARTIMSC, 0);
1171        // Disable interrupts (lower 11 bits)
1172        write(&mut serial, Register::UARTICR, 0x7ff);
1173        // Disable DMA on Rx and Tx
1174        write(&mut serial, Register::UARTDMACR, 0x0);
1175
1176        // Leave Rx and Tx enabled to drain FIFOs, wait a bit,
1177        // and then disable Rx, Tx, and UART.
1178        write(&mut serial, Register::UARTCR, UARTCR_RXE | UARTCR_TXE);
1179        read(&mut serial, Register::UARTCR);
1180        read(&mut serial, Register::UARTCR);
1181        write(&mut serial, Register::UARTCR, 0x0000);
1182
1183        // Set integer and fractinal parts of the baud rate,
1184        // hardcoded for now
1185        write(&mut serial, Register::UARTFBRD, 0x0004);
1186        write(&mut serial, Register::UARTIBRD, 0x0027);
1187        // The UARTLCR_H, UARTIBRD, and UARTFBRD registers form the single 30-bit
1188        // wide UARTLCR Register that is updated on a single write strobe generated by a
1189        // UARTLCR_H write
1190        write(
1191            &mut serial,
1192            Register::UARTLCR_H,
1193            UARTLCR_H_FIFO_ENABLE | UARTLCR_H_8BITS,
1194        );
1195
1196        // Enable Tx and Rx, wait a bit, and then enable UART
1197        write(&mut serial, Register::UARTCR, UARTCR_RXE | UARTCR_TXE);
1198        read(&mut serial, Register::UARTCR);
1199        read(&mut serial, Register::UARTCR);
1200        write(
1201            &mut serial,
1202            Register::UARTCR,
1203            UARTCR_RXE | UARTCR_TXE | UARTCR_UARTEN,
1204        );
1205    }
1206
1207    #[async_test]
1208    async fn test_writeread_data() {
1209        let serial_io = SerialIoMock::new();
1210        let mut serial = SerialPl011::new(
1211            "com1".to_string(),
1212            PL011_SERIAL0_BASE,
1213            LineInterrupt::detached(),
1214            Box::new(serial_io),
1215        )
1216        .unwrap();
1217
1218        write(&mut serial, Register::UARTCR, 0x400 | 0x800); // UARTCR_DTR | UARTCR_RTS
1219
1220        for n in 1..FIFO_SIZE as u16 {
1221            write(&mut serial, Register::UARTDR, n);
1222        }
1223
1224        poll_fn(|cx| {
1225            serial.poll_device(cx);
1226            std::task::Poll::Ready(())
1227        })
1228        .await;
1229
1230        for n in FIFO_SIZE as u16..1 {
1231            assert_eq!(read(&mut serial, Register::UARTDR), n);
1232        }
1233    }
1234
1235    #[test]
1236    fn test_write_ifls() {
1237        let serial_io = SerialIoMock::new();
1238        let mut serial = SerialPl011::new(
1239            "com1".to_string(),
1240            PL011_SERIAL0_BASE,
1241            LineInterrupt::detached(),
1242            Box::new(serial_io),
1243        )
1244        .unwrap();
1245
1246        write(&mut serial, Register::UARTIFLS, 0b000000);
1247        assert_eq!(u16::from(serial.state.ifls), 0b000000);
1248
1249        write(&mut serial, Register::UARTIFLS, 0b001001);
1250        assert_eq!(u16::from(serial.state.ifls), 0b001001);
1251
1252        write(&mut serial, Register::UARTIFLS, 0b100100);
1253        assert_eq!(u16::from(serial.state.ifls), 0b100100);
1254
1255        write(&mut serial, Register::UARTIFLS, 0b11001001);
1256        assert_eq!(u16::from(serial.state.ifls), 0b001001); // Drop extra bits
1257    }
1258
1259    #[test]
1260    fn test_write_icr() {
1261        let serial_io = SerialIoMock::new();
1262        let mut serial = SerialPl011::new(
1263            "com1".to_string(),
1264            PL011_SERIAL0_BASE,
1265            LineInterrupt::detached(),
1266            Box::new(serial_io),
1267        )
1268        .unwrap();
1269
1270        serial.state.ris = InterruptRegister::from(0b11111111111).clear_reserved();
1271        write(&mut serial, Register::UARTICR, 0b00000000000);
1272        assert_eq!(u16::from(serial.state.ris), 0b11110111111);
1273
1274        serial.state.ris = InterruptRegister::from(0b11111111111).clear_reserved();
1275        write(&mut serial, Register::UARTICR, 0b100000000000); // extra bit
1276        assert_eq!(u16::from(serial.state.ris), 0b11110111111);
1277
1278        serial.state.ris = InterruptRegister::from(0b11111111111).clear_reserved();
1279        write(&mut serial, Register::UARTICR, 0b11111111111);
1280        assert_eq!(u16::from(serial.state.ris), 0b00000000000);
1281
1282        serial.state.ris = InterruptRegister::from(0b11111111111).clear_reserved();
1283        write(&mut serial, Register::UARTICR, 0b111111111111); // extra bit
1284        assert_eq!(u16::from(serial.state.ris), 0b00000000000);
1285
1286        serial.state.ris = InterruptRegister::from(0b11111111111).clear_reserved();
1287        write(&mut serial, Register::UARTICR, 0b01111011110);
1288        assert_eq!(u16::from(serial.state.ris), 0b10000100001);
1289    }
1290}