Skip to content

Commit 5a05d0a

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

4 files changed

Lines changed: 72 additions & 19 deletions

File tree

drivers/gpu/drm/asahi/Kconfig

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

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: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use core::ops::Range;
1616
use core::sync::atomic::{AtomicBool, AtomicU64, Ordering};
1717

1818
use kernel::{
19-
c_str,
19+
c_str, devcoredump,
2020
error::code::*,
2121
macros::versions,
2222
new_mutex,
@@ -36,8 +36,7 @@ use crate::driver::{AsahiDevRef, AsahiDevice};
3636
use crate::fw::channels::{ChannelErrorType, PipeType};
3737
use crate::fw::types::{U32, U64};
3838
use crate::{
39-
alloc, buffer, channel, crashdump, event, fw, gem, hw, initdata, mem, mmu, queue, regs,
40-
workqueue,
39+
alloc, buffer, channel, event, fw, gem, hw, initdata, mem, mmu, queue, regs, workqueue,
4140
};
4241

4342
const DEBUG_CLASS: DebugFlags = DebugFlags::Gpu;
@@ -336,8 +335,9 @@ impl rtkit::Operations for GpuManager::ver {
336335

337336
data.crashed.store(true, Ordering::Relaxed);
338337

338+
#[cfg(CONFIG_DEV_COREDUMP)]
339339
if let Err(e) = data.generate_crashdump(crashlog) {
340-
dev_err!(dev.as_ref(), "Could not dump kernel VM pages: {:?}\n", e);
340+
dev_err!(dev.as_ref(), "Could not generate crashdump: {:?}\n", e);
341341
}
342342

343343
if debug_enabled(DebugFlags::OopsOnGpuCrash) {
@@ -1118,19 +1118,28 @@ impl GpuManager::ver {
11181118
Ok(())
11191119
}
11201120

1121+
#[cfg(CONFIG_DEV_COREDUMP)]
11211122
fn generate_crashdump(&self, crashlog: Option<&[u8]>) -> Result {
11221123
// Lock the allocators, to block kernel/FW memory mutations (mostly)
11231124
let kalloc = self.alloc();
11241125
let pages = self.uat.dump_kernel_pages()?;
11251126
core::mem::drop(kalloc);
11261127

1127-
let mut crashdump = crashdump::CrashDumpBuilder::new(pages)?;
1128+
let mut crashdump = crate::crashdump::CrashDumpBuilder::new(pages)?;
11281129
let initdata_addr = self.initdata.gpu_va().get();
11291130
crashdump.add_agx_info(self.cfg, &self.dyncfg, initdata_addr)?;
11301131
if let Some(crashlog) = crashlog {
11311132
crashdump.add_crashlog(crashlog)?;
11321133
}
1133-
let crashdump = crashdump.finalize();
1134+
let crashdump = KBox::new(crashdump.finalize()?, GFP_KERNEL)?;
1135+
1136+
devcoredump::dev_coredump(
1137+
self.dev.as_ref(),
1138+
&crate::THIS_MODULE,
1139+
crashdump,
1140+
GFP_KERNEL,
1141+
msecs_to_jiffies(60 * 60 * 1000),
1142+
);
11341143

11351144
Ok(())
11361145
}

0 commit comments

Comments
 (0)