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