// Copyright 2020 The Chromium OS Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. use std::fmt::{self, Display}; use std::fs::OpenOptions; use std::io; use crate::Pstore; use kvm::Vm; use resources::SystemAllocator; use resources::{Alloc, MmioType}; use sys_util::{GuestAddress, MemoryMapping}; /// Error for pstore. #[derive(Debug)] pub enum Error { IoError(io::Error), MmapError(sys_util::MmapError), ResourcesError(resources::Error), SysUtilError(sys_util::Error), } impl Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use self::Error::*; match self { IoError(e) => write!(f, "failed to create pstore backend file: {}", e), MmapError(e) => write!(f, "failed to get file mapped address: {}", e), ResourcesError(e) => write!(f, "failed to allocate pstore region: {}", e), SysUtilError(e) => write!(f, "file to add pstore region to mmio: {}", e), } } } impl std::error::Error for Error {} type Result = std::result::Result; pub struct RamoopsRegion { pub address: u64, pub size: u32, } /// Creates a mmio memory region for pstore. pub fn create_memory_region( vm: &mut Vm, resources: &mut SystemAllocator, pstore: &Pstore, ) -> Result { let file = OpenOptions::new() .read(true) .write(true) .create(true) .open(&pstore.path) .map_err(Error::IoError)?; file.set_len(pstore.size as u64).map_err(Error::IoError)?; let address = resources .mmio_allocator(MmioType::High) .allocate(pstore.size as u64, Alloc::Pstore, "pstore".to_owned()) .map_err(Error::ResourcesError)?; let memory_mapping = MemoryMapping::from_fd(&file, pstore.size as usize).map_err(Error::MmapError)?; vm.add_memory_region( GuestAddress(address), Box::new(memory_mapping), false, false, ) .map_err(Error::SysUtilError)?; Ok(RamoopsRegion { address, size: pstore.size, }) }