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 std::collections::VecDeque; 11 use std::fmt; 12 use std::sync::{Arc, Barrier}; 13 use std::{io, result}; 14 use versionize::{VersionMap, Versionize, VersionizeResult}; 15 use versionize_derive::Versionize; 16 use vm_device::interrupt::InterruptSourceGroup; 17 use vm_device::BusDevice; 18 use vm_migration::{ 19 Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable, VersionMapped, 20 }; 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 38 const PL011_INT_TX: u32 = 0x20; 39 const PL011_INT_RX: u32 = 0x10; 40 41 const PL011_FLAG_RXFF: u32 = 0x40; 42 const PL011_FLAG_RXFE: u32 = 0x10; 43 44 const PL011_ID: [u8; 8] = [0x11, 0x10, 0x14, 0x00, 0x0d, 0xf0, 0x05, 0xb1]; 45 // We are only interested in the margins. 46 const AMBA_ID_LOW: u64 = 0x3f8; 47 const AMBA_ID_HIGH: u64 = 0x401; 48 49 #[derive(Debug)] 50 pub enum Error { 51 BadWriteOffset(u64), 52 DmaNotImplemented, 53 InterruptFailure(io::Error), 54 WriteAllFailure(io::Error), 55 FlushFailure(io::Error), 56 } 57 58 impl fmt::Display for Error { 59 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 60 match self { 61 Error::BadWriteOffset(offset) => write!(f, "pl011_write: Bad Write Offset: {}", offset), 62 Error::DmaNotImplemented => write!(f, "pl011: DMA not implemented."), 63 Error::InterruptFailure(e) => write!(f, "Failed to trigger interrupt: {}", e), 64 Error::WriteAllFailure(e) => write!(f, "Failed to write: {}", e), 65 Error::FlushFailure(e) => write!(f, "Failed to flush: {}", e), 66 } 67 } 68 } 69 70 type Result<T> = result::Result<T, Error>; 71 72 /// A PL011 device following the PL011 specification. 73 pub struct Pl011 { 74 id: String, 75 flags: u32, 76 lcr: u32, 77 rsr: u32, 78 cr: u32, 79 dmacr: 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 } 92 93 #[derive(Versionize)] 94 pub struct Pl011State { 95 flags: u32, 96 lcr: u32, 97 rsr: u32, 98 cr: u32, 99 dmacr: u32, 100 int_enabled: u32, 101 int_level: u32, 102 read_fifo: Vec<u8>, 103 ilpr: u32, 104 ibrd: u32, 105 fbrd: u32, 106 ifl: u32, 107 read_count: u32, 108 read_trigger: u32, 109 } 110 111 impl VersionMapped for Pl011State {} 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 ) -> Self { 120 Self { 121 id, 122 flags: 0x90u32, 123 lcr: 0u32, 124 rsr: 0u32, 125 cr: 0x300u32, 126 dmacr: 0u32, 127 int_enabled: 0u32, 128 int_level: 0u32, 129 read_fifo: VecDeque::new(), 130 ilpr: 0u32, 131 ibrd: 0u32, 132 fbrd: 0u32, 133 ifl: 0x12u32, 134 read_count: 0u32, 135 read_trigger: 1u32, 136 irq, 137 out, 138 } 139 } 140 141 fn state(&self) -> Pl011State { 142 Pl011State { 143 flags: self.flags, 144 lcr: self.lcr, 145 rsr: self.rsr, 146 cr: self.cr, 147 dmacr: self.dmacr, 148 int_enabled: self.int_enabled, 149 int_level: self.int_level, 150 read_fifo: self.read_fifo.clone().into(), 151 ilpr: self.ilpr, 152 ibrd: self.ibrd, 153 fbrd: self.fbrd, 154 ifl: self.ifl, 155 read_count: self.read_count, 156 read_trigger: self.read_trigger, 157 } 158 } 159 160 fn set_state(&mut self, state: &Pl011State) { 161 self.flags = state.flags; 162 self.lcr = state.lcr; 163 self.rsr = state.rsr; 164 self.cr = state.cr; 165 self.dmacr = state.dmacr; 166 self.int_enabled = state.int_enabled; 167 self.int_level = state.int_level; 168 self.read_fifo = state.read_fifo.clone().into(); 169 self.ilpr = state.ilpr; 170 self.ibrd = state.ibrd; 171 self.fbrd = state.fbrd; 172 self.ifl = state.ifl; 173 self.read_count = state.read_count; 174 self.read_trigger = state.read_trigger; 175 } 176 177 /// Queues raw bytes for the guest to read and signals the interrupt 178 pub fn queue_input_bytes(&mut self, c: &[u8]) -> vmm_sys_util::errno::Result<()> { 179 self.read_fifo.extend(c); 180 self.read_count += c.len() as u32; 181 self.flags &= !PL011_FLAG_RXFE; 182 183 if ((self.lcr & 0x10) == 0) || (self.read_count == 16) { 184 self.flags |= PL011_FLAG_RXFF; 185 } 186 187 if self.read_count >= self.read_trigger { 188 self.int_level |= PL011_INT_RX; 189 self.trigger_interrupt()?; 190 } 191 192 Ok(()) 193 } 194 195 fn pl011_get_baudrate(&self) -> u32 { 196 if self.fbrd == 0 { 197 return 0; 198 } 199 200 let clk = 24_000_000; // We set the APB_PLCK to 24M in device tree 201 (clk / ((self.ibrd << 6) + self.fbrd)) << 2 202 } 203 204 fn pl011_trace_baudrate_change(&self) { 205 debug!( 206 "=== New baudrate: {:#?} (clk: {:#?}Hz, ibrd: {:#?}, fbrd: {:#?}) ===", 207 self.pl011_get_baudrate(), 208 24_000_000, // We set the APB_PLCK to 24M in device tree 209 self.ibrd, 210 self.fbrd 211 ); 212 } 213 214 fn pl011_set_read_trigger(&mut self) { 215 self.read_trigger = 1; 216 } 217 218 fn handle_write(&mut self, offset: u64, val: u32) -> Result<()> { 219 match offset >> 2 { 220 UARTDR => { 221 self.int_level |= PL011_INT_TX; 222 if let Some(out) = self.out.as_mut() { 223 out.write_all(&[val.to_le_bytes()[0]]) 224 .map_err(Error::WriteAllFailure)?; 225 out.flush().map_err(Error::FlushFailure)?; 226 } 227 } 228 UARTRSR_UARTECR => { 229 self.rsr = 0; 230 } 231 UARTFR => { /* Writes to Flag register are ignored.*/ } 232 UARTILPR => { 233 self.ilpr = val; 234 } 235 UARTIBRD => { 236 self.ibrd = val; 237 self.pl011_trace_baudrate_change(); 238 } 239 UARTFBRD => { 240 self.fbrd = val; 241 self.pl011_trace_baudrate_change(); 242 } 243 UARTLCR_H => { 244 /* Reset the FIFO state on FIFO enable or disable */ 245 if ((self.lcr ^ val) & 0x10) != 0 { 246 self.read_count = 0; 247 } 248 self.lcr = val; 249 self.pl011_set_read_trigger(); 250 } 251 UARTCR => { 252 self.cr = val; 253 } 254 UARTIFLS => { 255 self.ifl = val; 256 self.pl011_set_read_trigger(); 257 } 258 UARTIMSC => { 259 self.int_enabled = val; 260 self.trigger_interrupt().map_err(Error::InterruptFailure)?; 261 } 262 UARTICR => { 263 self.int_level &= !val; 264 self.trigger_interrupt().map_err(Error::InterruptFailure)?; 265 } 266 UARTDMACR => { 267 self.dmacr = val; 268 if (val & 3) != 0 { 269 return Err(Error::DmaNotImplemented); 270 } 271 } 272 off => { 273 return Err(Error::BadWriteOffset(off)); 274 } 275 } 276 Ok(()) 277 } 278 279 fn trigger_interrupt(&mut self) -> result::Result<(), io::Error> { 280 self.irq.trigger(0) 281 } 282 } 283 284 impl BusDevice for Pl011 { 285 fn read(&mut self, _base: u64, offset: u64, data: &mut [u8]) { 286 let v; 287 let mut read_ok = true; 288 if (AMBA_ID_LOW..AMBA_ID_HIGH).contains(&(offset >> 2)) { 289 let index = ((offset - 0xfe0) >> 2) as usize; 290 v = u32::from(PL011_ID[index]); 291 } else { 292 v = match offset >> 2 { 293 UARTDR => { 294 let c: u32; 295 let r: u32; 296 297 self.flags &= !PL011_FLAG_RXFF; 298 c = self.read_fifo.pop_front().unwrap_or_default().into(); 299 if self.read_count > 0 { 300 self.read_count -= 1; 301 } 302 if self.read_count == 0 { 303 self.flags |= PL011_FLAG_RXFE; 304 } 305 if self.read_count == (self.read_trigger - 1) { 306 self.int_level &= !PL011_INT_RX; 307 } 308 self.rsr = c >> 8; 309 r = c; 310 r 311 } 312 UARTRSR_UARTECR => self.rsr, 313 UARTFR => self.flags, 314 UARTILPR => self.ilpr, 315 UARTIBRD => self.ibrd, 316 UARTFBRD => self.fbrd, 317 UARTLCR_H => self.lcr, 318 UARTCR => self.cr, 319 UARTIFLS => self.ifl, 320 UARTIMSC => self.int_enabled, 321 UARTRIS => self.int_level, 322 UARTMIS => (self.int_level & self.int_enabled), 323 UARTDMACR => self.dmacr, 324 _ => { 325 read_ok = false; 326 0 327 } 328 } 329 } 330 331 if read_ok && data.len() <= 4 { 332 write_le_u32(data, v); 333 } else { 334 warn!( 335 "Invalid PL011 read: offset {}, data length {}", 336 offset, 337 data.len() 338 ); 339 } 340 } 341 342 fn write(&mut self, _base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> { 343 if data.len() <= 4 { 344 let v = read_le_u32(data); 345 if let Err(e) = self.handle_write(offset, v) { 346 warn!("Failed to write to PL011 device: {}", e); 347 } 348 } else { 349 warn!( 350 "Invalid PL011 write: offset {}, data length {}", 351 offset, 352 data.len() 353 ); 354 } 355 356 None 357 } 358 } 359 360 impl Snapshottable for Pl011 { 361 fn id(&self) -> String { 362 self.id.clone() 363 } 364 365 fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> { 366 Snapshot::new_from_versioned_state(&self.id, &self.state()) 367 } 368 369 fn restore(&mut self, snapshot: Snapshot) -> std::result::Result<(), MigratableError> { 370 self.set_state(&snapshot.to_versioned_state(&self.id)?); 371 Ok(()) 372 } 373 } 374 375 impl Pausable for Pl011 {} 376 impl Transportable for Pl011 {} 377 impl Migratable for Pl011 {} 378 379 #[cfg(test)] 380 mod tests { 381 use super::*; 382 use std::io; 383 use std::sync::{Arc, Mutex}; 384 use vm_device::interrupt::{InterruptIndex, InterruptSourceConfig}; 385 use vmm_sys_util::eventfd::EventFd; 386 387 const SERIAL_NAME: &str = "serial"; 388 389 struct TestInterrupt { 390 event_fd: EventFd, 391 } 392 393 impl InterruptSourceGroup for TestInterrupt { 394 fn trigger(&self, _index: InterruptIndex) -> result::Result<(), std::io::Error> { 395 self.event_fd.write(1) 396 } 397 fn update( 398 &self, 399 _index: InterruptIndex, 400 _config: InterruptSourceConfig, 401 ) -> result::Result<(), std::io::Error> { 402 Ok(()) 403 } 404 fn notifier(&self, _index: InterruptIndex) -> Option<EventFd> { 405 Some(self.event_fd.try_clone().unwrap()) 406 } 407 } 408 409 impl TestInterrupt { 410 fn new(event_fd: EventFd) -> Self { 411 TestInterrupt { event_fd } 412 } 413 } 414 415 #[derive(Clone)] 416 struct SharedBuffer { 417 buf: Arc<Mutex<Vec<u8>>>, 418 } 419 420 impl SharedBuffer { 421 fn new() -> SharedBuffer { 422 SharedBuffer { 423 buf: Arc::new(Mutex::new(Vec::new())), 424 } 425 } 426 } 427 428 impl io::Write for SharedBuffer { 429 fn write(&mut self, buf: &[u8]) -> io::Result<usize> { 430 self.buf.lock().unwrap().write(buf) 431 } 432 fn flush(&mut self) -> io::Result<()> { 433 self.buf.lock().unwrap().flush() 434 } 435 } 436 437 #[test] 438 fn pl011_output() { 439 let intr_evt = EventFd::new(0).unwrap(); 440 let pl011_out = SharedBuffer::new(); 441 let mut pl011 = Pl011::new( 442 String::from(SERIAL_NAME), 443 Arc::new(TestInterrupt::new(intr_evt.try_clone().unwrap())), 444 Some(Box::new(pl011_out.clone())), 445 ); 446 447 pl011.write(0, UARTDR as u64, &[b'x', b'y']); 448 pl011.write(0, UARTDR as u64, &[b'a']); 449 pl011.write(0, UARTDR as u64, &[b'b']); 450 pl011.write(0, UARTDR as u64, &[b'c']); 451 assert_eq!( 452 pl011_out.buf.lock().unwrap().as_slice(), 453 &[b'x', b'a', b'b', b'c'] 454 ); 455 } 456 457 #[test] 458 fn pl011_input() { 459 let intr_evt = EventFd::new(0).unwrap(); 460 let pl011_out = SharedBuffer::new(); 461 let mut pl011 = Pl011::new( 462 String::from(SERIAL_NAME), 463 Arc::new(TestInterrupt::new(intr_evt.try_clone().unwrap())), 464 Some(Box::new(pl011_out)), 465 ); 466 467 // write 1 to the interrupt event fd, so that read doesn't block in case the event fd 468 // counter doesn't change (for 0 it blocks) 469 assert!(intr_evt.write(1).is_ok()); 470 pl011.queue_input_bytes(&[b'a', b'b', b'c']).unwrap(); 471 472 assert_eq!(intr_evt.read().unwrap(), 2); 473 474 let mut data = [0u8]; 475 pl011.read(0, UARTDR as u64, &mut data); 476 assert_eq!(data[0], b'a'); 477 pl011.read(0, UARTDR as u64, &mut data); 478 assert_eq!(data[0], b'b'); 479 pl011.read(0, UARTDR as u64, &mut data); 480 assert_eq!(data[0], b'c'); 481 } 482 } 483