1 // Copyright 2020 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 use std::fmt::{self, Display};
6 use std::fs::OpenOptions;
7 use std::io;
8
9 use crate::Pstore;
10 use base::MemoryMappingBuilder;
11 use hypervisor::Vm;
12 use resources::SystemAllocator;
13 use resources::{Alloc, MmioType};
14 use vm_memory::GuestAddress;
15
16 /// Error for pstore.
17 #[derive(Debug)]
18 pub enum Error {
19 IoError(io::Error),
20 MmapError(base::MmapError),
21 ResourcesError(resources::Error),
22 SysUtilError(base::Error),
23 }
24
25 impl Display for Error {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result26 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
27 use self::Error::*;
28
29 match self {
30 IoError(e) => write!(f, "failed to create pstore backend file: {}", e),
31 MmapError(e) => write!(f, "failed to get file mapped address: {}", e),
32 ResourcesError(e) => write!(f, "failed to allocate pstore region: {}", e),
33 SysUtilError(e) => write!(f, "file to add pstore region to mmio: {}", e),
34 }
35 }
36 }
37
38 impl std::error::Error for Error {}
39 type Result<T> = std::result::Result<T, Error>;
40
41 pub struct RamoopsRegion {
42 pub address: u64,
43 pub size: u32,
44 }
45
46 /// Creates a mmio memory region for pstore.
create_memory_region( vm: &mut impl Vm, resources: &mut SystemAllocator, pstore: &Pstore, ) -> Result<RamoopsRegion>47 pub fn create_memory_region(
48 vm: &mut impl Vm,
49 resources: &mut SystemAllocator,
50 pstore: &Pstore,
51 ) -> Result<RamoopsRegion> {
52 let file = OpenOptions::new()
53 .read(true)
54 .write(true)
55 .create(true)
56 .open(&pstore.path)
57 .map_err(Error::IoError)?;
58 file.set_len(pstore.size as u64).map_err(Error::IoError)?;
59
60 let address = resources
61 .mmio_allocator(MmioType::High)
62 .allocate(pstore.size as u64, Alloc::Pstore, "pstore".to_owned())
63 .map_err(Error::ResourcesError)?;
64
65 let memory_mapping = MemoryMappingBuilder::new(pstore.size as usize)
66 .from_file(&file)
67 .build()
68 .map_err(Error::MmapError)?;
69
70 vm.add_memory_region(
71 GuestAddress(address),
72 Box::new(memory_mapping),
73 false,
74 false,
75 )
76 .map_err(Error::SysUtilError)?;
77
78 Ok(RamoopsRegion {
79 address,
80 size: pstore.size,
81 })
82 }
83