Skip to content

Commit d17aabe

Browse files
hoshinolinajannau
authored andcommitted
drm/asahi: Hook up crashdump to devcoredump
Signed-off-by: Asahi Lina <lina@asahilina.net>
1 parent 7e251b8 commit d17aabe

4 files changed

Lines changed: 75 additions & 17 deletions

File tree

drivers/gpu/drm/asahi/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ config DRM_ASAHI
2424
select RUST_DRM_GEM_SHMEM_HELPER
2525
select RUST_DRM_GPUVM
2626
select RUST_APPLE_RTKIT
27+
select WANT_DEV_COREDUMP
2728
help
2829
DRM driver for Apple AGX GPUs (G13x, found in the M1 SoC family)
2930

drivers/gpu/drm/asahi/asahi.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
mod alloc;
77
mod buffer;
88
mod channel;
9+
#[cfg(CONFIG_DEV_COREDUMP)]
910
mod crashdump;
1011
mod debug;
1112
mod driver;

drivers/gpu/drm/asahi/crashdump.rs

Lines changed: 55 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,28 @@
77
88
use core::mem::size_of;
99

10-
use kernel::{error::Result, page::Page, prelude::*, types::Owned};
10+
use kernel::{
11+
devcoredump::DevCoreDump,
12+
error::Result,
13+
page::{Page, PAGE_MASK, PAGE_SHIFT, PAGE_SIZE},
14+
prelude::*,
15+
types::Owned,
16+
uapi,
17+
};
1118

1219
use crate::hw;
1320
use crate::pgtable::{self, DumpedPage, Prot, UAT_PGSZ};
1421
use crate::util::align;
15-
use kernel::uapi;
1622

1723
pub(crate) struct CrashDump {
1824
headers: KVVec<u8>,
1925
pages: KVVec<Owned<Page>>,
2026
}
2127

22-
const NOTE_NAME_AGX: &str = &"AGX";
28+
const NOTE_NAME_AGX: &str = "AGX";
2329
const NOTE_AGX_DUMP_INFO: u32 = 1;
2430

25-
const NOTE_NAME_RTKIT: &str = &"RTKIT";
31+
const NOTE_NAME_RTKIT: &str = "RTKIT";
2632
const NOTE_RTKIT_CRASHLOG: u32 = 1;
2733

2834
#[repr(C)]
@@ -47,8 +53,12 @@ pub(crate) struct CrashDumpBuilder {
4753
notes: KVec<ELFNote>,
4854
}
4955

50-
// Helper to convert ELF headers into byte slices
51-
// TODO: Hook this up into kernel::AsBytes somehow
56+
/// Helper to convert ELF headers into byte slices
57+
/// TODO: Hook this up into kernel::AsBytes somehow
58+
///
59+
/// # Safety
60+
///
61+
/// Types implementing this trait must have no padding bytes.
5262
unsafe trait AsBytes: Sized {
5363
fn as_bytes(&self) -> &[u8] {
5464
// SAFETY: This trait is only implemented for types with no padding bytes
@@ -57,10 +67,7 @@ unsafe trait AsBytes: Sized {
5767
fn slice_as_bytes(slice: &[Self]) -> &[u8] {
5868
// SAFETY: This trait is only implemented for types with no padding bytes
5969
unsafe {
60-
core::slice::from_raw_parts(
61-
slice.as_ptr() as *const u8,
62-
slice.len() * size_of::<Self>(),
63-
)
70+
core::slice::from_raw_parts(slice.as_ptr() as *const u8, core::mem::size_of_val(slice))
6471
}
6572
}
6673
}
@@ -118,7 +125,7 @@ impl CrashDumpBuilder {
118125

119126
pub(crate) fn add_crashlog(&mut self, crashlog: &[u8]) -> Result {
120127
let mut data = KVVec::new();
121-
data.extend_from_slice(&crashlog, GFP_KERNEL)?;
128+
data.extend_from_slice(crashlog, GFP_KERNEL)?;
122129

123130
self.notes.push(
124131
ELFNote {
@@ -143,7 +150,7 @@ impl CrashDumpBuilder {
143150
ehdr.e_ident[uapi::EI_VERSION as usize] = uapi::EV_CURRENT as u8;
144151
ehdr.e_type = uapi::ET_CORE as u16;
145152
ehdr.e_machine = uapi::EM_AARCH64 as u16;
146-
ehdr.e_version = uapi::EV_CURRENT as u32;
153+
ehdr.e_version = uapi::EV_CURRENT;
147154
ehdr.e_entry = FIRMWARE_ENTRYPOINT;
148155
ehdr.e_ehsize = core::mem::size_of::<uapi::Elf64_Ehdr>() as u16;
149156
ehdr.e_phentsize = core::mem::size_of::<uapi::Elf64_Phdr>() as u16;
@@ -188,7 +195,6 @@ impl CrashDumpBuilder {
188195
p_memsz: UAT_PGSZ as u64,
189196
p_flags: flags,
190197
p_align: UAT_PGSZ as u64,
191-
..Default::default()
192198
},
193199
GFP_KERNEL,
194200
)?;
@@ -261,3 +267,39 @@ impl CrashDumpBuilder {
261267
Ok(CrashDump { headers, pages })
262268
}
263269
}
270+
271+
impl DevCoreDump for CrashDump {
272+
fn read(&self, buf: &mut [u8], mut offset: usize) -> Result<usize> {
273+
let mut read = 0;
274+
let mut left = buf.len();
275+
if offset < self.headers.len() {
276+
let block = left.min(self.headers.len() - offset);
277+
buf[..block].copy_from_slice(&self.headers[offset..offset + block]);
278+
read += block;
279+
offset += block;
280+
left -= block;
281+
}
282+
if left == 0 {
283+
return Ok(read);
284+
}
285+
offset -= self.headers.len(); // Offset from the page area
286+
287+
while left > 0 {
288+
let page_index = offset >> PAGE_SHIFT;
289+
let page_offset = offset & !PAGE_MASK;
290+
let block = left.min(PAGE_SIZE - page_offset);
291+
let Some(page) = self.pages.get(page_index) else {
292+
break;
293+
};
294+
let slice = &mut buf[read..read + block];
295+
// SAFETY: We own the page, and the slice guarantees the
296+
// dst length is sufficient.
297+
unsafe { page.read_raw(slice.as_mut_ptr(), page_offset, slice.len())? };
298+
read += block;
299+
offset += block;
300+
left -= block;
301+
}
302+
303+
Ok(read)
304+
}
305+
}

drivers/gpu/drm/asahi/gpu.rs

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,17 @@ use kernel::{
3737
UniqueArc, //
3838
},
3939
time::{
40-
msecs_to_jiffies,
4140
Delta,
4241
Instant,
4342
Monotonic, //
4443
},
4544
types::ForeignOwnable, //
4645
};
46+
#[cfg(CONFIG_DEV_COREDUMP)]
47+
use kernel::{
48+
devcoredump,
49+
time::msecs_to_jiffies, //
50+
};
4751

4852
use crate::alloc::Allocator;
4953
use crate::debug::*;
@@ -370,8 +374,9 @@ impl rtkit::Operations for GpuManager::ver {
370374

371375
data.crashed.store(true, Ordering::Relaxed);
372376

377+
#[cfg(CONFIG_DEV_COREDUMP)]
373378
if let Err(e) = data.generate_crashdump(crashlog) {
374-
dev_err!(dev.as_ref(), "Could not dump kernel VM pages: {:?}\n", e);
379+
dev_err!(dev.as_ref(), "Could not generate crashdump: {:?}\n", e);
375380
}
376381
#[cfg(not(CONFIG_DEV_COREDUMP))]
377382
let _ = crashlog;
@@ -1156,19 +1161,28 @@ impl GpuManager::ver {
11561161
Ok(())
11571162
}
11581163

1164+
#[cfg(CONFIG_DEV_COREDUMP)]
11591165
fn generate_crashdump(&self, crashlog: Option<&[u8]>) -> Result {
11601166
// Lock the allocators, to block kernel/FW memory mutations (mostly)
11611167
let kalloc = self.alloc();
11621168
let pages = self.uat.dump_kernel_pages()?;
11631169
core::mem::drop(kalloc);
11641170

1165-
let mut crashdump = crashdump::CrashDumpBuilder::new(pages)?;
1171+
let mut crashdump = crate::crashdump::CrashDumpBuilder::new(pages)?;
11661172
let initdata_addr = self.initdata.gpu_va().get();
11671173
crashdump.add_agx_info(self.cfg, &self.dyncfg, initdata_addr)?;
11681174
if let Some(crashlog) = crashlog {
11691175
crashdump.add_crashlog(crashlog)?;
11701176
}
1171-
let crashdump = crashdump.finalize();
1177+
let crashdump = KBox::new(crashdump.finalize()?, GFP_KERNEL)?;
1178+
1179+
devcoredump::dev_coredump(
1180+
self.dev.as_ref(),
1181+
&crate::THIS_MODULE,
1182+
crashdump,
1183+
GFP_KERNEL,
1184+
msecs_to_jiffies(60 * 60 * 1000),
1185+
);
11721186

11731187
Ok(())
11741188
}

0 commit comments

Comments
 (0)