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