1 // Copyright 2021 Arm Limited (or its affiliates). All rights reserved. 2 // 3 // SPDX-License-Identifier: Apache-2.0 4 5 //! ARM PrimeCell General Purpose Input/Output(PL061) 6 //! 7 //! This module implements an ARM PrimeCell General Purpose Input/Output(PL061) to support gracefully poweroff microvm from external. 8 //! 9 10 use std::io; 11 use std::result; 12 use std::sync::{Arc, Barrier}; 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 const OFS_DATA: u64 = 0x400; // Data Register 23 const GPIODIR: u64 = 0x400; // Direction Register 24 const GPIOIS: u64 = 0x404; // Interrupt Sense Register 25 const GPIOIBE: u64 = 0x408; // Interrupt Both Edges Register 26 const GPIOIEV: u64 = 0x40c; // Interrupt Event Register 27 const GPIOIE: u64 = 0x410; // Interrupt Mask Register 28 const GPIORIE: u64 = 0x414; // Raw Interrupt Status Register 29 const GPIOMIS: u64 = 0x418; // Masked Interrupt Status Register 30 const GPIOIC: u64 = 0x41c; // Interrupt Clear Register 31 const GPIOAFSEL: u64 = 0x420; // Mode Control Select Register 32 // From 0x424 to 0xFDC => reserved space. 33 // From 0xFE0 to 0xFFC => Peripheral and PrimeCell Identification Registers which are Read Only registers. 34 // These registers can conceptually be treated as a 32-bit register, and PartNumber[11:0] is used to identify the peripheral. 35 // We are putting the expected values (look at 'Reset value' column from above mentioned document) in an array. 36 const GPIO_ID: [u8; 8] = [0x61, 0x10, 0x14, 0x00, 0x0d, 0xf0, 0x05, 0xb1]; 37 // ID Margins 38 const GPIO_ID_LOW: u64 = 0xfe0; 39 const GPIO_ID_HIGH: u64 = 0x1000; 40 41 const N_GPIOS: u32 = 8; 42 43 #[derive(Debug, Error)] 44 pub enum Error { 45 #[error("Bad Write Offset: {0}")] 46 BadWriteOffset(u64), 47 #[error("GPIO interrupt disabled by guest driver.")] 48 GpioInterruptDisabled, 49 #[error("Could not trigger GPIO interrupt: {0}.")] 50 GpioInterruptFailure(io::Error), 51 #[error("Invalid GPIO Input key triggered: {0}.")] 52 GpioTriggerKeyFailure(u32), 53 } 54 55 type Result<T> = result::Result<T, Error>; 56 57 /// A GPIO device following the PL061 specification. 58 pub struct Gpio { 59 id: String, 60 // Data Register 61 data: u32, 62 old_in_data: u32, 63 // Direction Register 64 dir: u32, 65 // Interrupt Sense Register 66 isense: u32, 67 // Interrupt Both Edges Register 68 ibe: u32, 69 // Interrupt Event Register 70 iev: u32, 71 // Interrupt Mask Register 72 im: u32, 73 // Raw Interrupt Status Register 74 istate: u32, 75 // Mode Control Select Register 76 afsel: u32, 77 // GPIO irq_field 78 interrupt: Arc<dyn InterruptSourceGroup>, 79 } 80 81 #[derive(Serialize, Deserialize)] 82 pub struct GpioState { 83 data: u32, 84 old_in_data: u32, 85 dir: u32, 86 isense: u32, 87 ibe: u32, 88 iev: u32, 89 im: u32, 90 istate: u32, 91 afsel: u32, 92 } 93 94 impl Gpio { 95 /// Constructs an PL061 GPIO device. 96 pub fn new( 97 id: String, 98 interrupt: Arc<dyn InterruptSourceGroup>, 99 state: Option<GpioState>, 100 ) -> Self { 101 let (data, old_in_data, dir, isense, ibe, iev, im, istate, afsel) = 102 if let Some(state) = state { 103 ( 104 state.data, 105 state.old_in_data, 106 state.dir, 107 state.isense, 108 state.ibe, 109 state.iev, 110 state.im, 111 state.istate, 112 state.afsel, 113 ) 114 } else { 115 (0, 0, 0, 0, 0, 0, 0, 0, 0) 116 }; 117 118 Self { 119 id, 120 data, 121 old_in_data, 122 dir, 123 isense, 124 ibe, 125 iev, 126 im, 127 istate, 128 afsel, 129 interrupt, 130 } 131 } 132 133 fn state(&self) -> GpioState { 134 GpioState { 135 data: self.data, 136 old_in_data: self.old_in_data, 137 dir: self.dir, 138 isense: self.isense, 139 ibe: self.ibe, 140 iev: self.iev, 141 im: self.im, 142 istate: self.istate, 143 afsel: self.afsel, 144 } 145 } 146 147 fn pl061_internal_update(&mut self) { 148 // FIXME: 149 // Missing Output Interrupt Emulation. 150 151 // Input Edging Interrupt Emulation. 152 let changed = (self.old_in_data ^ self.data) & !self.dir; 153 if changed > 0 { 154 self.old_in_data = self.data; 155 for i in 0..N_GPIOS { 156 let mask = (1 << i) as u32; 157 if (changed & mask) > 0 { 158 // Bits set high in GPIOIS(Interrupt sense register) configure the corresponding 159 // pins to detect levels, otherwise, detect edges. 160 if (self.isense & mask) == 0 { 161 if (self.ibe & mask) > 0 { 162 // Bits set high in GPIOIBE(Interrupt both-edges register) configure the corresponding 163 // pins to detect both falling and rising edges. 164 // Clearing a bit configures the pin to be controlled by GPIOIEV. 165 self.istate |= mask; 166 } else { 167 // Bits set to high in GPIOIEV(Interrupt event register) configure the 168 // corresponding pin to detect rising edges, otherwise, detect falling edges. 169 self.istate |= !(self.data ^ self.iev) & mask; 170 } 171 } 172 } 173 } 174 } 175 176 // Input Level Interrupt Emulation. 177 self.istate |= !(self.data ^ self.iev) & self.isense; 178 } 179 180 fn handle_write(&mut self, offset: u64, val: u32) -> Result<()> { 181 if offset < OFS_DATA { 182 // In order to write to data register, the corresponding bits in the mask, resulting 183 // from the offsite[9:2], must be HIGH. otherwise the bit values remain unchanged. 184 let mask = (offset >> 2) as u32 & self.dir; 185 self.data = (self.data & !mask) | (val & mask); 186 } else { 187 match offset { 188 GPIODIR => { 189 /* Direction Register */ 190 self.dir = val & 0xff; 191 } 192 GPIOIS => { 193 /* Interrupt Sense Register */ 194 self.isense = val & 0xff; 195 } 196 GPIOIBE => { 197 /* Interrupt Both Edges Register */ 198 self.ibe = val & 0xff; 199 } 200 GPIOIEV => { 201 /* Interrupt Event Register */ 202 self.iev = val & 0xff; 203 } 204 GPIOIE => { 205 /* Interrupt Mask Register */ 206 self.im = val & 0xff; 207 } 208 GPIOIC => { 209 /* Interrupt Clear Register */ 210 self.istate &= !val; 211 } 212 GPIOAFSEL => { 213 /* Mode Control Select Register */ 214 self.afsel = val & 0xff; 215 } 216 o => { 217 return Err(Error::BadWriteOffset(o)); 218 } 219 } 220 } 221 Ok(()) 222 } 223 224 pub fn trigger_key(&mut self, key: u32) -> Result<()> { 225 let mask = (1 << key) as u32; 226 if (!self.dir & mask) > 0 { 227 // emulate key event 228 // By default, Input Pin is configured to detect both rising and falling edges. 229 // So reverse the input pin data to generate a pulse. 230 self.data |= !(self.data & mask) & mask; 231 self.pl061_internal_update(); 232 233 match self.trigger_gpio_interrupt() { 234 Ok(_) | Err(Error::GpioInterruptDisabled) => return Ok(()), 235 Err(e) => return Err(e), 236 } 237 } 238 239 Err(Error::GpioTriggerKeyFailure(key)) 240 } 241 242 fn trigger_gpio_interrupt(&self) -> Result<()> { 243 // Bits set to high in GPIOIE(Interrupt mask register) allow the corresponding pins to 244 // trigger their individual interrupts and then the combined GPIOINTR line. 245 if (self.istate & self.im) == 0 { 246 warn!("Failed to trigger GPIO input interrupt (disabled by guest OS)"); 247 return Err(Error::GpioInterruptDisabled); 248 } 249 self.interrupt 250 .trigger(0) 251 .map_err(Error::GpioInterruptFailure)?; 252 Ok(()) 253 } 254 } 255 256 impl BusDevice for Gpio { 257 fn read(&mut self, _base: u64, offset: u64, data: &mut [u8]) { 258 let value; 259 let mut read_ok = true; 260 261 if (GPIO_ID_LOW..GPIO_ID_HIGH).contains(&offset) { 262 let index = ((offset - GPIO_ID_LOW) >> 2) as usize; 263 value = u32::from(GPIO_ID[index]); 264 } else if offset < OFS_DATA { 265 value = self.data & ((offset >> 2) as u32) 266 } else { 267 value = match offset { 268 GPIODIR => self.dir, 269 GPIOIS => self.isense, 270 GPIOIBE => self.ibe, 271 GPIOIEV => self.iev, 272 GPIOIE => self.im, 273 GPIORIE => self.istate, 274 GPIOMIS => self.istate & self.im, 275 GPIOAFSEL => self.afsel, 276 _ => { 277 read_ok = false; 278 0 279 } 280 }; 281 } 282 283 if read_ok && data.len() <= 4 { 284 write_le_u32(data, value); 285 } else { 286 warn!( 287 "Invalid GPIO PL061 read: offset {}, data length {}", 288 offset, 289 data.len() 290 ); 291 } 292 } 293 294 fn write(&mut self, _base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> { 295 if data.len() <= 4 { 296 let value = read_le_u32(data); 297 if let Err(e) = self.handle_write(offset, value) { 298 warn!("Failed to write to GPIO PL061 device: {}", e); 299 } 300 } else { 301 warn!( 302 "Invalid GPIO PL061 write: offset {}, data length {}", 303 offset, 304 data.len() 305 ); 306 } 307 308 None 309 } 310 } 311 312 impl Snapshottable for Gpio { 313 fn id(&self) -> String { 314 self.id.clone() 315 } 316 317 fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> { 318 Snapshot::new_from_state(&self.state()) 319 } 320 } 321 322 impl Pausable for Gpio {} 323 impl Transportable for Gpio {} 324 impl Migratable for Gpio {} 325 326 #[cfg(test)] 327 mod tests { 328 use vm_device::interrupt::{InterruptIndex, InterruptSourceConfig}; 329 use vmm_sys_util::eventfd::EventFd; 330 331 use super::*; 332 333 const GPIO_NAME: &str = "gpio"; 334 const LEGACY_GPIO_MAPPED_IO_START: u64 = 0x0902_0000; 335 336 struct TestInterrupt { 337 event_fd: EventFd, 338 } 339 340 impl InterruptSourceGroup for TestInterrupt { 341 fn trigger(&self, _index: InterruptIndex) -> result::Result<(), std::io::Error> { 342 self.event_fd.write(1) 343 } 344 345 fn update( 346 &self, 347 _index: InterruptIndex, 348 _config: InterruptSourceConfig, 349 _masked: bool, 350 _set_gsi: bool, 351 ) -> result::Result<(), std::io::Error> { 352 Ok(()) 353 } 354 355 fn set_gsi(&self) -> result::Result<(), std::io::Error> { 356 Ok(()) 357 } 358 359 fn notifier(&self, _index: InterruptIndex) -> Option<EventFd> { 360 Some(self.event_fd.try_clone().unwrap()) 361 } 362 } 363 364 impl TestInterrupt { 365 fn new(event_fd: EventFd) -> Self { 366 TestInterrupt { event_fd } 367 } 368 } 369 370 #[test] 371 fn test_gpio_read_write_and_event() { 372 let intr_evt = EventFd::new(libc::EFD_NONBLOCK).unwrap(); 373 let mut gpio = Gpio::new( 374 String::from(GPIO_NAME), 375 Arc::new(TestInterrupt::new(intr_evt.try_clone().unwrap())), 376 None, 377 ); 378 let mut data = [0; 4]; 379 380 // Read and write to the GPIODIR register. 381 // Set pin 0 output pin. 382 write_le_u32(&mut data, 1); 383 gpio.write(LEGACY_GPIO_MAPPED_IO_START, GPIODIR, &data); 384 gpio.read(LEGACY_GPIO_MAPPED_IO_START, GPIODIR, &mut data); 385 let v = read_le_u32(&data); 386 assert_eq!(v, 1); 387 388 // Read and write to the GPIODATA register. 389 write_le_u32(&mut data, 1); 390 // Set pin 0 high. 391 let offset = 0x00000004_u64; 392 gpio.write(LEGACY_GPIO_MAPPED_IO_START, offset, &data); 393 gpio.read(LEGACY_GPIO_MAPPED_IO_START, offset, &mut data); 394 let v = read_le_u32(&data); 395 assert_eq!(v, 1); 396 397 // Read and write to the GPIOIS register. 398 // Configure pin 0 detecting level interrupt. 399 write_le_u32(&mut data, 1); 400 gpio.write(LEGACY_GPIO_MAPPED_IO_START, GPIOIS, &data); 401 gpio.read(LEGACY_GPIO_MAPPED_IO_START, GPIOIS, &mut data); 402 let v = read_le_u32(&data); 403 assert_eq!(v, 1); 404 405 // Read and write to the GPIOIBE register. 406 // Configure pin 1 detecting both falling and rising edges. 407 write_le_u32(&mut data, 2); 408 gpio.write(LEGACY_GPIO_MAPPED_IO_START, GPIOIBE, &data); 409 gpio.read(LEGACY_GPIO_MAPPED_IO_START, GPIOIBE, &mut data); 410 let v = read_le_u32(&data); 411 assert_eq!(v, 2); 412 413 // Read and write to the GPIOIEV register. 414 // Configure pin 2 detecting both falling and rising edges. 415 write_le_u32(&mut data, 4); 416 gpio.write(LEGACY_GPIO_MAPPED_IO_START, GPIOIEV, &data); 417 gpio.read(LEGACY_GPIO_MAPPED_IO_START, GPIOIEV, &mut data); 418 let v = read_le_u32(&data); 419 assert_eq!(v, 4); 420 421 // Read and write to the GPIOIE register. 422 // Configure pin 0...2 capable of triggering their individual interrupts 423 // and then the combined GPIOINTR line. 424 write_le_u32(&mut data, 7); 425 gpio.write(LEGACY_GPIO_MAPPED_IO_START, GPIOIE, &data); 426 gpio.read(LEGACY_GPIO_MAPPED_IO_START, GPIOIE, &mut data); 427 let v = read_le_u32(&data); 428 assert_eq!(v, 7); 429 430 let mask = 0x00000002_u32; 431 // emulate an rising pulse in pin 1. 432 gpio.data |= !(gpio.data & mask) & mask; 433 gpio.pl061_internal_update(); 434 // The interrupt line on pin 1 should be on. 435 // Read the GPIOMIS register. 436 gpio.read(LEGACY_GPIO_MAPPED_IO_START, GPIOMIS, &mut data); 437 let v = read_le_u32(&data); 438 assert_eq!(v, 2); 439 440 // Read and Write to the GPIOIC register. 441 // clear interrupt in pin 1. 442 write_le_u32(&mut data, 2); 443 gpio.write(LEGACY_GPIO_MAPPED_IO_START, GPIOIC, &data); 444 gpio.read(LEGACY_GPIO_MAPPED_IO_START, GPIOIC, &mut data); 445 let v = read_le_u32(&data); 446 assert_eq!(v, 2); 447 448 // Attempts to write beyond the writable space. 449 write_le_u32(&mut data, 0); 450 gpio.write(LEGACY_GPIO_MAPPED_IO_START, GPIO_ID_LOW, &data); 451 452 let mut data = [0; 4]; 453 gpio.read(LEGACY_GPIO_MAPPED_IO_START, GPIO_ID_LOW, &mut data); 454 let index = GPIO_ID_LOW + 3; 455 assert_eq!(data[0], GPIO_ID[((index - GPIO_ID_LOW) >> 2) as usize]); 456 } 457 } 458