1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
// Copyright 2020 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::fs::OpenOptions;

use anyhow::bail;
use anyhow::Context;
use anyhow::Result;
use base::MemoryMappingBuilder;
use hypervisor::MemCacheType;
use hypervisor::Vm;
use resources::AddressRange;
use vm_memory::GuestAddress;

use crate::Pstore;

mod sys;

pub struct RamoopsRegion {
    pub address: u64,
    pub size: u32,
}

/// Creates a mmio memory region for pstore.
pub fn create_memory_region(
    vm: &mut impl Vm,
    region: AddressRange,
    pstore: &Pstore,
) -> Result<RamoopsRegion> {
    let region_size = region.len().context("failed to get region len")?;
    if region_size < pstore.size.into() {
        bail!("insufficient space for pstore {} {}", region, pstore.size);
    }

    let mut open_opts = OpenOptions::new();
    open_opts.read(true).write(true).create(true);
    sys::set_extra_open_opts(&mut open_opts);

    let file = open_opts
        .open(&pstore.path)
        .context("failed to open pstore")?;
    file.set_len(pstore.size as u64)
        .context("failed to set pstore length")?;

    let memory_mapping = MemoryMappingBuilder::new(pstore.size as usize)
        .from_file(&file)
        .build()
        .context("failed to mmap pstore")?;

    vm.add_memory_region(
        GuestAddress(region.start),
        Box::new(memory_mapping),
        false,
        false,
        MemCacheType::CacheCoherent,
    )
    .context("failed to add pstore region")?;

    Ok(RamoopsRegion {
        address: region.start,
        size: pstore.size,
    })
}

pub fn add_ramoops_kernel_cmdline(
    cmdline: &mut kernel_cmdline::Cmdline,
    ramoops_region: &RamoopsRegion,
) -> std::result::Result<(), kernel_cmdline::Error> {
    // It seems that default record_size is only 4096 byte even if crosvm allocates
    // more memory. It means that one crash can only 4096 byte.
    // Set record_size and console_size to 1/4 of allocated memory size.
    // This configulation is same as the host.
    let ramoops_opts = [
        ("mem_address", ramoops_region.address),
        ("mem_size", ramoops_region.size as u64),
    ];
    for (name, val) in &ramoops_opts {
        cmdline.insert_str(format!("ramoops.{}={:#x}", name, val))?;
    }
    Ok(())
}