1fd95acc6SHenry Wang // Copyright 2021 Arm Limited (or its affiliates). All rights reserved. 2fd95acc6SHenry Wang // SPDX-License-Identifier: Apache-2.0 3fd95acc6SHenry Wang 4fd95acc6SHenry Wang //! ARM PrimeCell UART(PL011) 5fd95acc6SHenry Wang //! 6fd95acc6SHenry Wang //! This module implements an ARM PrimeCell UART(PL011). 7fd95acc6SHenry Wang //! 8fd95acc6SHenry Wang 9fd95acc6SHenry Wang use std::collections::VecDeque; 10fd95acc6SHenry Wang use std::sync::{Arc, Barrier}; 11707cea21SRob Bradford use std::time::Instant; 12fd95acc6SHenry Wang use std::{io, result}; 1388a9f799SRob Bradford 1488a9f799SRob Bradford use serde::{Deserialize, Serialize}; 1589b429c7SSamrutGadde use thiserror::Error; 16fd95acc6SHenry Wang use vm_device::interrupt::InterruptSourceGroup; 17fd95acc6SHenry Wang use vm_device::BusDevice; 1810ab87d6SRob Bradford use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable}; 19fd95acc6SHenry Wang 2088a9f799SRob Bradford use crate::{read_le_u32, write_le_u32}; 2188a9f799SRob Bradford 22fd95acc6SHenry Wang /* Registers */ 23fd95acc6SHenry Wang const UARTDR: u64 = 0; 24fd95acc6SHenry Wang const UARTRSR_UARTECR: u64 = 1; 25fd95acc6SHenry Wang const UARTFR: u64 = 6; 26fd95acc6SHenry Wang const UARTILPR: u64 = 8; 27fd95acc6SHenry Wang const UARTIBRD: u64 = 9; 28fd95acc6SHenry Wang const UARTFBRD: u64 = 10; 29fd95acc6SHenry Wang const UARTLCR_H: u64 = 11; 30fd95acc6SHenry Wang const UARTCR: u64 = 12; 31fd95acc6SHenry Wang const UARTIFLS: u64 = 13; 32fd95acc6SHenry Wang const UARTIMSC: u64 = 14; 33fd95acc6SHenry Wang const UARTRIS: u64 = 15; 34fd95acc6SHenry Wang const UARTMIS: u64 = 16; 35fd95acc6SHenry Wang const UARTICR: u64 = 17; 36fd95acc6SHenry Wang const UARTDMACR: u64 = 18; 376dbc1362SJianyong Wu const UARTDEBUG: u64 = 0x3c0; 38fd95acc6SHenry Wang 39fd95acc6SHenry Wang const PL011_INT_TX: u32 = 0x20; 40fd95acc6SHenry Wang const PL011_INT_RX: u32 = 0x10; 41fd95acc6SHenry Wang 42fd95acc6SHenry Wang const PL011_FLAG_RXFF: u32 = 0x40; 43fd95acc6SHenry Wang const PL011_FLAG_RXFE: u32 = 0x10; 44fd95acc6SHenry Wang 45fd95acc6SHenry Wang const PL011_ID: [u8; 8] = [0x11, 0x10, 0x14, 0x00, 0x0d, 0xf0, 0x05, 0xb1]; 46fd95acc6SHenry Wang // We are only interested in the margins. 47fd95acc6SHenry Wang const AMBA_ID_LOW: u64 = 0x3f8; 48fd95acc6SHenry Wang const AMBA_ID_HIGH: u64 = 0x401; 49fd95acc6SHenry Wang 5089b429c7SSamrutGadde #[derive(Debug, Error)] 51fd95acc6SHenry Wang pub enum Error { 5289b429c7SSamrutGadde #[error("pl011_write: Bad Write Offset: {0}")] 53fd95acc6SHenry Wang BadWriteOffset(u64), 54ab575a54SPhilipp Schuster #[error("pl011: DMA not implemented")] 5540da6210SRob Bradford DmaNotImplemented, 56*1b91aa8eSPhilipp Schuster #[error("Failed to trigger interrupt")] 5793b599e5SPhilipp Schuster InterruptFailure(#[source] io::Error), 58*1b91aa8eSPhilipp Schuster #[error("Failed to write")] 5993b599e5SPhilipp Schuster WriteAllFailure(#[source] io::Error), 60*1b91aa8eSPhilipp Schuster #[error("Failed to flush")] 6193b599e5SPhilipp Schuster FlushFailure(#[source] io::Error), 62fd95acc6SHenry Wang } 63fd95acc6SHenry Wang 64fd95acc6SHenry Wang type Result<T> = result::Result<T, Error>; 65fd95acc6SHenry Wang 66fd95acc6SHenry Wang /// A PL011 device following the PL011 specification. 6740da6210SRob Bradford pub struct Pl011 { 68fd95acc6SHenry Wang id: String, 69fd95acc6SHenry Wang flags: u32, 70fd95acc6SHenry Wang lcr: u32, 71fd95acc6SHenry Wang rsr: u32, 72fd95acc6SHenry Wang cr: u32, 73fd95acc6SHenry Wang dmacr: u32, 746dbc1362SJianyong Wu debug: u32, 75fd95acc6SHenry Wang int_enabled: u32, 76fd95acc6SHenry Wang int_level: u32, 77fd95acc6SHenry Wang read_fifo: VecDeque<u8>, 78fd95acc6SHenry Wang ilpr: u32, 79fd95acc6SHenry Wang ibrd: u32, 80fd95acc6SHenry Wang fbrd: u32, 81fd95acc6SHenry Wang ifl: u32, 82fd95acc6SHenry Wang read_count: u32, 83fd95acc6SHenry Wang read_trigger: u32, 84dcc646f5SSebastien Boeuf irq: Arc<dyn InterruptSourceGroup>, 85fd95acc6SHenry Wang out: Option<Box<dyn io::Write + Send>>, 866dbc1362SJianyong Wu timestamp: std::time::Instant, 87fd95acc6SHenry Wang } 88fd95acc6SHenry Wang 8910ab87d6SRob Bradford #[derive(Serialize, Deserialize)] 9040da6210SRob Bradford pub struct Pl011State { 91fd95acc6SHenry Wang flags: u32, 92fd95acc6SHenry Wang lcr: u32, 93fd95acc6SHenry Wang rsr: u32, 94fd95acc6SHenry Wang cr: u32, 95fd95acc6SHenry Wang dmacr: u32, 966dbc1362SJianyong Wu debug: u32, 97fd95acc6SHenry Wang int_enabled: u32, 98fd95acc6SHenry Wang int_level: u32, 99f643ba61SRob Bradford read_fifo: Vec<u8>, 100fd95acc6SHenry Wang ilpr: u32, 101fd95acc6SHenry Wang ibrd: u32, 102fd95acc6SHenry Wang fbrd: u32, 103fd95acc6SHenry Wang ifl: u32, 104fd95acc6SHenry Wang read_count: u32, 105fd95acc6SHenry Wang read_trigger: u32, 106fd95acc6SHenry Wang } 107fd95acc6SHenry Wang 10840da6210SRob Bradford impl Pl011 { 109fd95acc6SHenry Wang /// Constructs an AMBA PL011 UART device. new( id: String, irq: Arc<dyn InterruptSourceGroup>, out: Option<Box<dyn io::Write + Send>>, timestamp: Instant, state: Option<Pl011State>, ) -> Self110fd95acc6SHenry Wang pub fn new( 111fd95acc6SHenry Wang id: String, 112dcc646f5SSebastien Boeuf irq: Arc<dyn InterruptSourceGroup>, 113fd95acc6SHenry Wang out: Option<Box<dyn io::Write + Send>>, 114707cea21SRob Bradford timestamp: Instant, 1159fbf52b9SSebastien Boeuf state: Option<Pl011State>, 11640da6210SRob Bradford ) -> Self { 1179fbf52b9SSebastien Boeuf let ( 1189fbf52b9SSebastien Boeuf flags, 1199fbf52b9SSebastien Boeuf lcr, 1209fbf52b9SSebastien Boeuf rsr, 1219fbf52b9SSebastien Boeuf cr, 1229fbf52b9SSebastien Boeuf dmacr, 1239fbf52b9SSebastien Boeuf debug, 1249fbf52b9SSebastien Boeuf int_enabled, 1259fbf52b9SSebastien Boeuf int_level, 1269fbf52b9SSebastien Boeuf read_fifo, 1279fbf52b9SSebastien Boeuf ilpr, 1289fbf52b9SSebastien Boeuf ibrd, 1299fbf52b9SSebastien Boeuf fbrd, 1309fbf52b9SSebastien Boeuf ifl, 1319fbf52b9SSebastien Boeuf read_count, 1329fbf52b9SSebastien Boeuf read_trigger, 1339fbf52b9SSebastien Boeuf ) = if let Some(state) = state { 1349fbf52b9SSebastien Boeuf ( 1359fbf52b9SSebastien Boeuf state.flags, 1369fbf52b9SSebastien Boeuf state.lcr, 1379fbf52b9SSebastien Boeuf state.rsr, 1389fbf52b9SSebastien Boeuf state.cr, 1399fbf52b9SSebastien Boeuf state.dmacr, 1409fbf52b9SSebastien Boeuf state.debug, 1419fbf52b9SSebastien Boeuf state.int_enabled, 1429fbf52b9SSebastien Boeuf state.int_level, 1439fbf52b9SSebastien Boeuf state.read_fifo.into(), 1449fbf52b9SSebastien Boeuf state.ilpr, 1459fbf52b9SSebastien Boeuf state.ibrd, 1469fbf52b9SSebastien Boeuf state.fbrd, 1479fbf52b9SSebastien Boeuf state.ifl, 1489fbf52b9SSebastien Boeuf state.read_count, 1499fbf52b9SSebastien Boeuf state.read_trigger, 1509fbf52b9SSebastien Boeuf ) 1519fbf52b9SSebastien Boeuf } else { 1529fbf52b9SSebastien Boeuf ( 1539fbf52b9SSebastien Boeuf 0x90, 1549fbf52b9SSebastien Boeuf 0, 1559fbf52b9SSebastien Boeuf 0, 1569fbf52b9SSebastien Boeuf 0x300, 1579fbf52b9SSebastien Boeuf 0, 1589fbf52b9SSebastien Boeuf 0, 1599fbf52b9SSebastien Boeuf 0, 1609fbf52b9SSebastien Boeuf 0, 1619fbf52b9SSebastien Boeuf VecDeque::new(), 1629fbf52b9SSebastien Boeuf 0, 1639fbf52b9SSebastien Boeuf 0, 1649fbf52b9SSebastien Boeuf 0, 1659fbf52b9SSebastien Boeuf 0x12, 1669fbf52b9SSebastien Boeuf 0, 1679fbf52b9SSebastien Boeuf 1, 1689fbf52b9SSebastien Boeuf ) 1699fbf52b9SSebastien Boeuf }; 1709fbf52b9SSebastien Boeuf 17140da6210SRob Bradford Self { 172fd95acc6SHenry Wang id, 1739fbf52b9SSebastien Boeuf flags, 1749fbf52b9SSebastien Boeuf lcr, 1759fbf52b9SSebastien Boeuf rsr, 1769fbf52b9SSebastien Boeuf cr, 1779fbf52b9SSebastien Boeuf dmacr, 1789fbf52b9SSebastien Boeuf debug, 1799fbf52b9SSebastien Boeuf int_enabled, 1809fbf52b9SSebastien Boeuf int_level, 1819fbf52b9SSebastien Boeuf read_fifo, 1829fbf52b9SSebastien Boeuf ilpr, 1839fbf52b9SSebastien Boeuf ibrd, 1849fbf52b9SSebastien Boeuf fbrd, 1859fbf52b9SSebastien Boeuf ifl, 1869fbf52b9SSebastien Boeuf read_count, 1879fbf52b9SSebastien Boeuf read_trigger, 188fd95acc6SHenry Wang irq, 189fd95acc6SHenry Wang out, 190707cea21SRob Bradford timestamp, 191fd95acc6SHenry Wang } 192fd95acc6SHenry Wang } 193fd95acc6SHenry Wang set_out(&mut self, out: Option<Box<dyn io::Write + Send>>)1946d1077fcSPraveen K Paladugu pub fn set_out(&mut self, out: Option<Box<dyn io::Write + Send>>) { 1956d1077fcSPraveen K Paladugu self.out = out; 1960066ddefSWilliam Douglas } 1970066ddefSWilliam Douglas state(&self) -> Pl011State19840da6210SRob Bradford fn state(&self) -> Pl011State { 19940da6210SRob Bradford Pl011State { 200fd95acc6SHenry Wang flags: self.flags, 201fd95acc6SHenry Wang lcr: self.lcr, 202fd95acc6SHenry Wang rsr: self.rsr, 203fd95acc6SHenry Wang cr: self.cr, 204fd95acc6SHenry Wang dmacr: self.dmacr, 2056dbc1362SJianyong Wu debug: self.debug, 206fd95acc6SHenry Wang int_enabled: self.int_enabled, 207fd95acc6SHenry Wang int_level: self.int_level, 208f643ba61SRob Bradford read_fifo: self.read_fifo.clone().into(), 209fd95acc6SHenry Wang ilpr: self.ilpr, 210fd95acc6SHenry Wang ibrd: self.ibrd, 211fd95acc6SHenry Wang fbrd: self.fbrd, 212fd95acc6SHenry Wang ifl: self.ifl, 213fd95acc6SHenry Wang read_count: self.read_count, 214fd95acc6SHenry Wang read_trigger: self.read_trigger, 215fd95acc6SHenry Wang } 216fd95acc6SHenry Wang } 217fd95acc6SHenry Wang 218fd95acc6SHenry Wang /// Queues raw bytes for the guest to read and signals the interrupt queue_input_bytes(&mut self, c: &[u8]) -> vmm_sys_util::errno::Result<()>219fd95acc6SHenry Wang pub fn queue_input_bytes(&mut self, c: &[u8]) -> vmm_sys_util::errno::Result<()> { 220fd95acc6SHenry Wang self.read_fifo.extend(c); 221fd95acc6SHenry Wang self.read_count += c.len() as u32; 222fd95acc6SHenry Wang self.flags &= !PL011_FLAG_RXFE; 223fd95acc6SHenry Wang 224fd95acc6SHenry Wang if ((self.lcr & 0x10) == 0) || (self.read_count == 16) { 225fd95acc6SHenry Wang self.flags |= PL011_FLAG_RXFF; 226fd95acc6SHenry Wang } 227fd95acc6SHenry Wang 228fd95acc6SHenry Wang if self.read_count >= self.read_trigger { 229fd95acc6SHenry Wang self.int_level |= PL011_INT_RX; 230fd95acc6SHenry Wang self.trigger_interrupt()?; 231fd95acc6SHenry Wang } 232fd95acc6SHenry Wang 233fd95acc6SHenry Wang Ok(()) 234fd95acc6SHenry Wang } 235fd95acc6SHenry Wang flush_output(&mut self) -> result::Result<(), io::Error>2360066ddefSWilliam Douglas pub fn flush_output(&mut self) -> result::Result<(), io::Error> { 2370066ddefSWilliam Douglas if let Some(out) = self.out.as_mut() { 2380066ddefSWilliam Douglas out.flush()?; 2390066ddefSWilliam Douglas } 2400066ddefSWilliam Douglas Ok(()) 2410066ddefSWilliam Douglas } 2420066ddefSWilliam Douglas pl011_get_baudrate(&self) -> u32243fd95acc6SHenry Wang fn pl011_get_baudrate(&self) -> u32 { 244fd95acc6SHenry Wang if self.fbrd == 0 { 245fd95acc6SHenry Wang return 0; 246fd95acc6SHenry Wang } 247fd95acc6SHenry Wang 248fd95acc6SHenry Wang let clk = 24_000_000; // We set the APB_PLCK to 24M in device tree 249fd95acc6SHenry Wang (clk / ((self.ibrd << 6) + self.fbrd)) << 2 250fd95acc6SHenry Wang } 251fd95acc6SHenry Wang pl011_trace_baudrate_change(&self)252fd95acc6SHenry Wang fn pl011_trace_baudrate_change(&self) { 253fd95acc6SHenry Wang debug!( 254fd95acc6SHenry Wang "=== New baudrate: {:#?} (clk: {:#?}Hz, ibrd: {:#?}, fbrd: {:#?}) ===", 255fd95acc6SHenry Wang self.pl011_get_baudrate(), 256fd95acc6SHenry Wang 24_000_000, // We set the APB_PLCK to 24M in device tree 257fd95acc6SHenry Wang self.ibrd, 258fd95acc6SHenry Wang self.fbrd 259fd95acc6SHenry Wang ); 260fd95acc6SHenry Wang } 261fd95acc6SHenry Wang pl011_set_read_trigger(&mut self)262fd95acc6SHenry Wang fn pl011_set_read_trigger(&mut self) { 263fd95acc6SHenry Wang self.read_trigger = 1; 264fd95acc6SHenry Wang } 265fd95acc6SHenry Wang handle_write(&mut self, offset: u64, val: u32) -> Result<()>266fd95acc6SHenry Wang fn handle_write(&mut self, offset: u64, val: u32) -> Result<()> { 267fd95acc6SHenry Wang match offset >> 2 { 268fd95acc6SHenry Wang UARTDR => { 269fd95acc6SHenry Wang self.int_level |= PL011_INT_TX; 270fd95acc6SHenry Wang if let Some(out) = self.out.as_mut() { 271fd95acc6SHenry Wang out.write_all(&[val.to_le_bytes()[0]]) 272fd95acc6SHenry Wang .map_err(Error::WriteAllFailure)?; 273fd95acc6SHenry Wang out.flush().map_err(Error::FlushFailure)?; 274fd95acc6SHenry Wang } 275fd95acc6SHenry Wang } 276fd95acc6SHenry Wang UARTRSR_UARTECR => { 277fd95acc6SHenry Wang self.rsr = 0; 278fd95acc6SHenry Wang } 279fd95acc6SHenry Wang UARTFR => { /* Writes to Flag register are ignored.*/ } 280fd95acc6SHenry Wang UARTILPR => { 281fd95acc6SHenry Wang self.ilpr = val; 282fd95acc6SHenry Wang } 283fd95acc6SHenry Wang UARTIBRD => { 284fd95acc6SHenry Wang self.ibrd = val; 285fd95acc6SHenry Wang self.pl011_trace_baudrate_change(); 286fd95acc6SHenry Wang } 287fd95acc6SHenry Wang UARTFBRD => { 288fd95acc6SHenry Wang self.fbrd = val; 289fd95acc6SHenry Wang self.pl011_trace_baudrate_change(); 290fd95acc6SHenry Wang } 291fd95acc6SHenry Wang UARTLCR_H => { 292fd95acc6SHenry Wang /* Reset the FIFO state on FIFO enable or disable */ 293fd95acc6SHenry Wang if ((self.lcr ^ val) & 0x10) != 0 { 294fd95acc6SHenry Wang self.read_count = 0; 295fd95acc6SHenry Wang } 296fd95acc6SHenry Wang self.lcr = val; 297fd95acc6SHenry Wang self.pl011_set_read_trigger(); 298fd95acc6SHenry Wang } 299fd95acc6SHenry Wang UARTCR => { 300fd95acc6SHenry Wang self.cr = val; 301fd95acc6SHenry Wang } 302fd95acc6SHenry Wang UARTIFLS => { 303fd95acc6SHenry Wang self.ifl = val; 304fd95acc6SHenry Wang self.pl011_set_read_trigger(); 305fd95acc6SHenry Wang } 306fd95acc6SHenry Wang UARTIMSC => { 307fd95acc6SHenry Wang self.int_enabled = val; 308fd95acc6SHenry Wang self.trigger_interrupt().map_err(Error::InterruptFailure)?; 309fd95acc6SHenry Wang } 310fd95acc6SHenry Wang UARTICR => { 311fd95acc6SHenry Wang self.int_level &= !val; 312fd95acc6SHenry Wang self.trigger_interrupt().map_err(Error::InterruptFailure)?; 313fd95acc6SHenry Wang } 314fd95acc6SHenry Wang UARTDMACR => { 315fd95acc6SHenry Wang self.dmacr = val; 316fd95acc6SHenry Wang if (val & 3) != 0 { 31740da6210SRob Bradford return Err(Error::DmaNotImplemented); 318fd95acc6SHenry Wang } 319fd95acc6SHenry Wang } 3206dbc1362SJianyong Wu UARTDEBUG => { 3216dbc1362SJianyong Wu self.debug = val; 3226dbc1362SJianyong Wu self.handle_debug(); 3236dbc1362SJianyong Wu } 324fd95acc6SHenry Wang off => { 3256dbc1362SJianyong Wu debug!("PL011: Bad write offset, offset: {}", off); 326fd95acc6SHenry Wang return Err(Error::BadWriteOffset(off)); 327fd95acc6SHenry Wang } 328fd95acc6SHenry Wang } 329fd95acc6SHenry Wang Ok(()) 330fd95acc6SHenry Wang } 331fd95acc6SHenry Wang handle_debug(&self)3326dbc1362SJianyong Wu fn handle_debug(&self) { 3336dbc1362SJianyong Wu let elapsed = self.timestamp.elapsed(); 3346dbc1362SJianyong Wu 3356dbc1362SJianyong Wu match self.debug { 33619b006ebSRob Bradford 0x00..=0x1f => warn!( 3376dbc1362SJianyong Wu "[Debug I/O port: Firmware code: 0x{:x}] {}.{:>06} seconds", 3386dbc1362SJianyong Wu self.debug, 3396dbc1362SJianyong Wu elapsed.as_secs(), 3406dbc1362SJianyong Wu elapsed.as_micros() 3416dbc1362SJianyong Wu ), 34219b006ebSRob Bradford 0x20..=0x3f => warn!( 3436dbc1362SJianyong Wu "[Debug I/O port: Bootloader code: 0x{:x}] {}.{:>06} seconds", 3446dbc1362SJianyong Wu self.debug, 3456dbc1362SJianyong Wu elapsed.as_secs(), 3466dbc1362SJianyong Wu elapsed.as_micros() 3476dbc1362SJianyong Wu ), 34819b006ebSRob Bradford 0x40..=0x5f => warn!( 3496dbc1362SJianyong Wu "[Debug I/O port: Kernel code: 0x{:x}] {}.{:>06} seconds", 3506dbc1362SJianyong Wu self.debug, 3516dbc1362SJianyong Wu elapsed.as_secs(), 3526dbc1362SJianyong Wu elapsed.as_micros() 3536dbc1362SJianyong Wu ), 35419b006ebSRob Bradford 0x60..=0x7f => warn!( 3556dbc1362SJianyong Wu "[Debug I/O port: Userspace code: 0x{:x}] {}.{:>06} seconds", 3566dbc1362SJianyong Wu self.debug, 3576dbc1362SJianyong Wu elapsed.as_secs(), 3586dbc1362SJianyong Wu elapsed.as_micros() 3596dbc1362SJianyong Wu ), 3606dbc1362SJianyong Wu _ => {} 3616dbc1362SJianyong Wu } 3626dbc1362SJianyong Wu } 3636dbc1362SJianyong Wu trigger_interrupt(&mut self) -> result::Result<(), io::Error>364fd95acc6SHenry Wang fn trigger_interrupt(&mut self) -> result::Result<(), io::Error> { 365fd95acc6SHenry Wang self.irq.trigger(0) 366fd95acc6SHenry Wang } 367fd95acc6SHenry Wang } 368fd95acc6SHenry Wang 36940da6210SRob Bradford impl BusDevice for Pl011 { read(&mut self, _base: u64, offset: u64, data: &mut [u8])370fd95acc6SHenry Wang fn read(&mut self, _base: u64, offset: u64, data: &mut [u8]) { 371fd95acc6SHenry Wang let mut read_ok = true; 3721dc91342SRob Bradford let v = if (AMBA_ID_LOW..AMBA_ID_HIGH).contains(&(offset >> 2)) { 373fd95acc6SHenry Wang let index = ((offset - 0xfe0) >> 2) as usize; 3741dc91342SRob Bradford u32::from(PL011_ID[index]) 375fd95acc6SHenry Wang } else { 3761dc91342SRob Bradford match offset >> 2 { 377fd95acc6SHenry Wang UARTDR => { 378fd95acc6SHenry Wang self.flags &= !PL011_FLAG_RXFF; 3791dc91342SRob Bradford let c: u32 = self.read_fifo.pop_front().unwrap_or_default().into(); 380fd95acc6SHenry Wang if self.read_count > 0 { 381fd95acc6SHenry Wang self.read_count -= 1; 382fd95acc6SHenry Wang } 383fd95acc6SHenry Wang if self.read_count == 0 { 384fd95acc6SHenry Wang self.flags |= PL011_FLAG_RXFE; 385fd95acc6SHenry Wang } 386fd95acc6SHenry Wang if self.read_count == (self.read_trigger - 1) { 387fd95acc6SHenry Wang self.int_level &= !PL011_INT_RX; 388fd95acc6SHenry Wang } 389fd95acc6SHenry Wang self.rsr = c >> 8; 3901dc91342SRob Bradford c 391fd95acc6SHenry Wang } 392fd95acc6SHenry Wang UARTRSR_UARTECR => self.rsr, 393fd95acc6SHenry Wang UARTFR => self.flags, 394fd95acc6SHenry Wang UARTILPR => self.ilpr, 395fd95acc6SHenry Wang UARTIBRD => self.ibrd, 396fd95acc6SHenry Wang UARTFBRD => self.fbrd, 397fd95acc6SHenry Wang UARTLCR_H => self.lcr, 398fd95acc6SHenry Wang UARTCR => self.cr, 399fd95acc6SHenry Wang UARTIFLS => self.ifl, 400fd95acc6SHenry Wang UARTIMSC => self.int_enabled, 401fd95acc6SHenry Wang UARTRIS => self.int_level, 402f42c6d56SWei Liu UARTMIS => self.int_level & self.int_enabled, 403fd95acc6SHenry Wang UARTDMACR => self.dmacr, 4046dbc1362SJianyong Wu UARTDEBUG => self.debug, 405fd95acc6SHenry Wang _ => { 406fd95acc6SHenry Wang read_ok = false; 407fd95acc6SHenry Wang 0 408fd95acc6SHenry Wang } 409fd95acc6SHenry Wang } 4101dc91342SRob Bradford }; 411fd95acc6SHenry Wang 412fd95acc6SHenry Wang if read_ok && data.len() <= 4 { 413fd95acc6SHenry Wang write_le_u32(data, v); 414fd95acc6SHenry Wang } else { 415fd95acc6SHenry Wang warn!( 416fd95acc6SHenry Wang "Invalid PL011 read: offset {}, data length {}", 417fd95acc6SHenry Wang offset, 418fd95acc6SHenry Wang data.len() 419fd95acc6SHenry Wang ); 420fd95acc6SHenry Wang } 421fd95acc6SHenry Wang } 422fd95acc6SHenry Wang write(&mut self, _base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>>423fd95acc6SHenry Wang fn write(&mut self, _base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> { 424fd95acc6SHenry Wang if data.len() <= 4 { 4255825ab2dSBo Chen let v = read_le_u32(data); 426fd95acc6SHenry Wang if let Err(e) = self.handle_write(offset, v) { 427fd95acc6SHenry Wang warn!("Failed to write to PL011 device: {}", e); 428fd95acc6SHenry Wang } 429fd95acc6SHenry Wang } else { 430fd95acc6SHenry Wang warn!( 431fd95acc6SHenry Wang "Invalid PL011 write: offset {}, data length {}", 432fd95acc6SHenry Wang offset, 433fd95acc6SHenry Wang data.len() 434fd95acc6SHenry Wang ); 435fd95acc6SHenry Wang } 436fd95acc6SHenry Wang 437fd95acc6SHenry Wang None 438fd95acc6SHenry Wang } 439fd95acc6SHenry Wang } 440fd95acc6SHenry Wang 44140da6210SRob Bradford impl Snapshottable for Pl011 { id(&self) -> String442fd95acc6SHenry Wang fn id(&self) -> String { 443fd95acc6SHenry Wang self.id.clone() 444fd95acc6SHenry Wang } 445fd95acc6SHenry Wang snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError>446fd95acc6SHenry Wang fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> { 44710ab87d6SRob Bradford Snapshot::new_from_state(&self.state()) 448fd95acc6SHenry Wang } 449fd95acc6SHenry Wang } 450fd95acc6SHenry Wang 45140da6210SRob Bradford impl Pausable for Pl011 {} 45240da6210SRob Bradford impl Transportable for Pl011 {} 45340da6210SRob Bradford impl Migratable for Pl011 {} 454fd95acc6SHenry Wang 455fd95acc6SHenry Wang #[cfg(test)] 456fd95acc6SHenry Wang mod tests { 457f093ffcbSRob Bradford use std::sync::Mutex; 45888a9f799SRob Bradford 459fd95acc6SHenry Wang use vm_device::interrupt::{InterruptIndex, InterruptSourceConfig}; 460fd95acc6SHenry Wang use vmm_sys_util::eventfd::EventFd; 461fd95acc6SHenry Wang 46288a9f799SRob Bradford use super::*; 46388a9f799SRob Bradford 464fd95acc6SHenry Wang const SERIAL_NAME: &str = "serial"; 465fd95acc6SHenry Wang 466fd95acc6SHenry Wang struct TestInterrupt { 467fd95acc6SHenry Wang event_fd: EventFd, 468fd95acc6SHenry Wang } 469fd95acc6SHenry Wang 470fd95acc6SHenry Wang impl InterruptSourceGroup for TestInterrupt { trigger(&self, _index: InterruptIndex) -> result::Result<(), std::io::Error>471fd95acc6SHenry Wang fn trigger(&self, _index: InterruptIndex) -> result::Result<(), std::io::Error> { 472fd95acc6SHenry Wang self.event_fd.write(1) 473fd95acc6SHenry Wang } update( &self, _index: InterruptIndex, _config: InterruptSourceConfig, _masked: bool, _set_gsi: bool, ) -> result::Result<(), std::io::Error>474fd95acc6SHenry Wang fn update( 475fd95acc6SHenry Wang &self, 476fd95acc6SHenry Wang _index: InterruptIndex, 477fd95acc6SHenry Wang _config: InterruptSourceConfig, 478ed87e42eSRob Bradford _masked: bool, 4790149e650SYong He _set_gsi: bool, 480fd95acc6SHenry Wang ) -> result::Result<(), std::io::Error> { 481fd95acc6SHenry Wang Ok(()) 482fd95acc6SHenry Wang } set_gsi(&self) -> result::Result<(), std::io::Error>4830149e650SYong He fn set_gsi(&self) -> result::Result<(), std::io::Error> { 4840149e650SYong He Ok(()) 4850149e650SYong He } notifier(&self, _index: InterruptIndex) -> Option<EventFd>486fd95acc6SHenry Wang fn notifier(&self, _index: InterruptIndex) -> Option<EventFd> { 487fd95acc6SHenry Wang Some(self.event_fd.try_clone().unwrap()) 488fd95acc6SHenry Wang } 489fd95acc6SHenry Wang } 490fd95acc6SHenry Wang 491fd95acc6SHenry Wang impl TestInterrupt { new(event_fd: EventFd) -> Self492fd95acc6SHenry Wang fn new(event_fd: EventFd) -> Self { 493fd95acc6SHenry Wang TestInterrupt { event_fd } 494fd95acc6SHenry Wang } 495fd95acc6SHenry Wang } 496fd95acc6SHenry Wang 497fd95acc6SHenry Wang #[derive(Clone)] 498fd95acc6SHenry Wang struct SharedBuffer { 499fd95acc6SHenry Wang buf: Arc<Mutex<Vec<u8>>>, 500fd95acc6SHenry Wang } 501fd95acc6SHenry Wang 502fd95acc6SHenry Wang impl SharedBuffer { new() -> SharedBuffer503fd95acc6SHenry Wang fn new() -> SharedBuffer { 504fd95acc6SHenry Wang SharedBuffer { 505fd95acc6SHenry Wang buf: Arc::new(Mutex::new(Vec::new())), 506fd95acc6SHenry Wang } 507fd95acc6SHenry Wang } 508fd95acc6SHenry Wang } 509fd95acc6SHenry Wang 510fd95acc6SHenry Wang impl io::Write for SharedBuffer { write(&mut self, buf: &[u8]) -> io::Result<usize>511fd95acc6SHenry Wang fn write(&mut self, buf: &[u8]) -> io::Result<usize> { 512fd95acc6SHenry Wang self.buf.lock().unwrap().write(buf) 513fd95acc6SHenry Wang } flush(&mut self) -> io::Result<()>514fd95acc6SHenry Wang fn flush(&mut self) -> io::Result<()> { 515fd95acc6SHenry Wang self.buf.lock().unwrap().flush() 516fd95acc6SHenry Wang } 517fd95acc6SHenry Wang } 518fd95acc6SHenry Wang 519fd95acc6SHenry Wang #[test] pl011_output()520fd95acc6SHenry Wang fn pl011_output() { 521fd95acc6SHenry Wang let intr_evt = EventFd::new(0).unwrap(); 522fd95acc6SHenry Wang let pl011_out = SharedBuffer::new(); 52340da6210SRob Bradford let mut pl011 = Pl011::new( 524fd95acc6SHenry Wang String::from(SERIAL_NAME), 525dcc646f5SSebastien Boeuf Arc::new(TestInterrupt::new(intr_evt.try_clone().unwrap())), 526fd95acc6SHenry Wang Some(Box::new(pl011_out.clone())), 527707cea21SRob Bradford Instant::now(), 5289fbf52b9SSebastien Boeuf None, 529fd95acc6SHenry Wang ); 530fd95acc6SHenry Wang 5318aa2d7abSWei Liu pl011.write(0, UARTDR, b"xy"); 5328aa2d7abSWei Liu pl011.write(0, UARTDR, b"a"); 5338aa2d7abSWei Liu pl011.write(0, UARTDR, b"b"); 5348aa2d7abSWei Liu pl011.write(0, UARTDR, b"c"); 5358aa2d7abSWei Liu assert_eq!(pl011_out.buf.lock().unwrap().as_slice(), b"xabc"); 536fd95acc6SHenry Wang } 537fd95acc6SHenry Wang 538fd95acc6SHenry Wang #[test] pl011_input()539fd95acc6SHenry Wang fn pl011_input() { 540fd95acc6SHenry Wang let intr_evt = EventFd::new(0).unwrap(); 541fd95acc6SHenry Wang let pl011_out = SharedBuffer::new(); 54240da6210SRob Bradford let mut pl011 = Pl011::new( 543fd95acc6SHenry Wang String::from(SERIAL_NAME), 544dcc646f5SSebastien Boeuf Arc::new(TestInterrupt::new(intr_evt.try_clone().unwrap())), 545fd95acc6SHenry Wang Some(Box::new(pl011_out)), 546707cea21SRob Bradford Instant::now(), 5479fbf52b9SSebastien Boeuf None, 548fd95acc6SHenry Wang ); 549fd95acc6SHenry Wang 550fd95acc6SHenry Wang // write 1 to the interrupt event fd, so that read doesn't block in case the event fd 551fd95acc6SHenry Wang // counter doesn't change (for 0 it blocks) 552297236a7SRuoqing He intr_evt.write(1).unwrap(); 5538aa2d7abSWei Liu pl011.queue_input_bytes(b"abc").unwrap(); 554fd95acc6SHenry Wang 555fd95acc6SHenry Wang assert_eq!(intr_evt.read().unwrap(), 2); 556fd95acc6SHenry Wang 557fd95acc6SHenry Wang let mut data = [0u8]; 5583888f576SRob Bradford pl011.read(0, UARTDR, &mut data); 559fd95acc6SHenry Wang assert_eq!(data[0], b'a'); 5603888f576SRob Bradford pl011.read(0, UARTDR, &mut data); 561fd95acc6SHenry Wang assert_eq!(data[0], b'b'); 5623888f576SRob Bradford pl011.read(0, UARTDR, &mut data); 563fd95acc6SHenry Wang assert_eq!(data[0], b'c'); 564fd95acc6SHenry Wang } 565fd95acc6SHenry Wang } 566