Skip to content

Commit 1e1c97c

Browse files
committed
drm/asahi: Port to kernel::uaccess
Allows to drop kernel::io_buffer and kernel::user_ptr Rust-for-Linux imports. Signed-off-by: Janne Grunau <j@jannau.net>
1 parent 6e350e3 commit 1e1c97c

4 files changed

Lines changed: 84 additions & 95 deletions

File tree

drivers/gpu/drm/asahi/file.rs

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,9 @@ use core::ops::Range;
1818
use kernel::dma_fence::RawDmaFence;
1919
use kernel::drm::gem::BaseObject;
2020
use kernel::error::code::*;
21-
use kernel::io_buffer::{IoBufferReader, IoBufferWriter};
2221
use kernel::prelude::*;
2322
use kernel::sync::{Arc, Mutex};
24-
use kernel::user_ptr::UserSlicePtr;
23+
use kernel::uaccess::{UserPtr, UserSlice};
2524
use kernel::{dma_fence, drm, uapi, xarray};
2625

2726
const DEBUG_CLASS: DebugFlags = DebugFlags::File;
@@ -142,13 +141,15 @@ impl SyncItem {
142141
let size = STRIDE * count as usize;
143142

144143
// SAFETY: We only read this once, so there are no TOCTOU issues.
145-
let mut reader = unsafe { UserSlicePtr::new(ptr as usize as *mut _, size).reader() };
144+
let mut reader = UserSlice::new(ptr as UserPtr, size).reader();
146145

147146
for _i in 0..count {
148147
let mut sync: MaybeUninit<uapi::drm_asahi_sync> = MaybeUninit::uninit();
149148

150149
// SAFETY: The size of `sync` is STRIDE
151-
unsafe { reader.read_raw(sync.as_mut_ptr() as *mut u8, STRIDE)? };
150+
reader.read_raw(unsafe {
151+
core::slice::from_raw_parts_mut(sync.as_mut_ptr() as *mut MaybeUninit<u8>, STRIDE)
152+
})?;
152153

153154
// SAFETY: All bit patterns in the struct are valid
154155
let sync = unsafe { sync.assume_init() };
@@ -307,11 +308,12 @@ impl File {
307308
let size = core::mem::size_of::<uapi::drm_asahi_params_global>().min(data.size.try_into()?);
308309

309310
// SAFETY: We only write to this userptr once, so there are no TOCTOU issues.
310-
let mut params_writer =
311-
unsafe { UserSlicePtr::new(data.pointer as usize as *mut _, size).writer() };
311+
let mut params_writer = UserSlice::new(data.pointer as UserPtr, size).writer();
312312

313313
// SAFETY: `size` is at most the sizeof of `params`
314-
unsafe { params_writer.write_raw(&params as *const _ as *const u8, size)? };
314+
params_writer.write_slice(unsafe {
315+
core::slice::from_raw_parts(&params as *const _ as *const u8, size)
316+
})?;
315317

316318
Ok(0)
317319
}
@@ -1061,14 +1063,15 @@ impl File {
10611063
let size = STRIDE * data.command_count as usize;
10621064

10631065
// SAFETY: We only read this once, so there are no TOCTOU issues.
1064-
let mut reader =
1065-
unsafe { UserSlicePtr::new(data.commands as usize as *mut _, size).reader() };
1066+
let mut reader = UserSlice::new(data.commands as UserPtr, size).reader();
10661067

10671068
for _i in 0..data.command_count {
10681069
let mut cmd: MaybeUninit<uapi::drm_asahi_command> = MaybeUninit::uninit();
10691070

1070-
// SAFETY: The size of `sync` is STRIDE
1071-
unsafe { reader.read_raw(cmd.as_mut_ptr() as *mut u8, STRIDE)? };
1071+
// SAFETY: The size of `cmd` is STRIDE
1072+
reader.read_raw(unsafe {
1073+
core::slice::from_raw_parts_mut(cmd.as_mut_ptr() as *mut MaybeUninit<u8>, STRIDE)
1074+
})?;
10721075

10731076
// SAFETY: All bit patterns in the struct are valid
10741077
commands.push(unsafe { cmd.assume_init() }, GFP_KERNEL)?;

drivers/gpu/drm/asahi/queue/common.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,9 @@ use crate::fw::job::UserTimestamp;
99
use crate::fw::microseq;
1010
use crate::fw::types::*;
1111

12-
use kernel::io_buffer::IoBufferReader;
1312
use kernel::prelude::*;
13+
use kernel::uaccess::{UserPtr, UserSlice};
1414
use kernel::uapi;
15-
use kernel::user_ptr::UserSlicePtr;
1615
use kernel::xarray;
1716

1817
use core::mem::MaybeUninit;
@@ -26,15 +25,17 @@ pub(super) fn build_attachments(pointer: u64, count: u32) -> Result<microseq::At
2625
let size = STRIDE * count as usize;
2726

2827
// SAFETY: We only read this once, so there are no TOCTOU issues.
29-
let mut reader = unsafe { UserSlicePtr::new(pointer as usize as *mut _, size).reader() };
28+
let mut reader = UserSlice::new(pointer as UserPtr, size).reader();
3029

3130
let mut attachments: microseq::Attachments = Default::default();
3231

3332
for i in 0..count {
3433
let mut att: MaybeUninit<uapi::drm_asahi_attachment> = MaybeUninit::uninit();
3534

3635
// SAFETY: The size of `att` is STRIDE
37-
unsafe { reader.read_raw(att.as_mut_ptr() as *mut u8, STRIDE)? };
36+
reader.read_raw(unsafe {
37+
core::slice::from_raw_parts_mut(att.as_mut_ptr() as *mut MaybeUninit<u8>, STRIDE)
38+
})?;
3839

3940
// SAFETY: All bit patterns in the struct are valid
4041
let att = unsafe { att.assume_init() };

drivers/gpu/drm/asahi/queue/compute.rs

Lines changed: 28 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,14 @@ use crate::fw::types::*;
1414
use crate::gpu::GpuManager;
1515
use crate::{file, fw, gpu, microseq};
1616
use crate::{inner_ptr, inner_weak_ptr};
17+
use core::mem::MaybeUninit;
1718
use core::sync::atomic::Ordering;
1819
use kernel::dma_fence::RawDmaFence;
1920
use kernel::drm::sched::Job;
20-
use kernel::io_buffer::IoBufferReader;
2121
use kernel::prelude::*;
2222
use kernel::sync::Arc;
23+
use kernel::uaccess::{UserPtr, UserSlice};
2324
use kernel::uapi;
24-
use kernel::user_ptr::UserSlicePtr;
2525
use kernel::xarray;
2626

2727
const DEBUG_CLASS: DebugFlags = DebugFlags::Compute;
@@ -58,21 +58,20 @@ impl super::QueueInner::ver {
5858

5959
let cmdbuf_read_size =
6060
(cmd.cmd_buffer_size as usize).min(core::mem::size_of::<uapi::drm_asahi_cmd_compute>());
61-
// SAFETY: This is the sole UserSlicePtr instance for this cmd_buffer.
62-
let mut cmdbuf_reader = unsafe {
63-
UserSlicePtr::new(
64-
cmd.cmd_buffer as usize as *mut _,
65-
cmd.cmd_buffer_size as usize,
66-
)
67-
.reader()
68-
};
61+
// SAFETY: This is the sole UserSlice instance for this cmd_buffer.
62+
let mut cmdbuf_reader =
63+
UserSlice::new(cmd.cmd_buffer as UserPtr, cmd.cmd_buffer_size as usize).reader();
6964

7065
let mut cmdbuf: uapi::drm_asahi_cmd_compute = Default::default();
7166
// SAFETY: The output pointer is valid, and the size does not exceed the type size
7267
// per the min() above, and all bit patterns are valid.
73-
unsafe {
74-
cmdbuf_reader.read_raw(&mut cmdbuf as *mut _ as *mut u8, cmdbuf_read_size)?;
75-
}
68+
// cmdbuf_reader.read_raw(&mut cmdbuf as *mut _ as *mut MaybeUninit<u8>, cmdbuf_read_size)})?;
69+
cmdbuf_reader.read_raw(unsafe {
70+
core::slice::from_raw_parts_mut(
71+
&mut cmdbuf as *mut _ as *mut MaybeUninit<u8>,
72+
cmdbuf_read_size,
73+
)
74+
})?;
7675

7776
if cmdbuf.flags & !(uapi::ASAHI_COMPUTE_NO_PREEMPTION as u64) != 0 {
7877
return Err(EINVAL);
@@ -82,37 +81,32 @@ impl super::QueueInner::ver {
8281

8382
let mut ext_ptr = cmdbuf.extensions;
8483
while ext_ptr != 0 {
85-
let ext_type = u32::from_ne_bytes(
86-
// SAFETY: There is a double read from userspace here, but there is no TOCTOU
87-
// issue since at worst the extension parse below will read garbage, and
88-
// we do not trust any fields anyway.
89-
unsafe { UserSlicePtr::new(ext_ptr as usize as *mut _, 4) }
90-
.read_all()?
91-
.try_into()
92-
.or(Err(EINVAL))?,
93-
);
84+
// SAFETY: There is a double read from userspace here, but there is no TOCTOU
85+
// issue since at worst the extension parse below will read garbage, and
86+
// we do not trust any fields anyway.
87+
let ext_type = UserSlice::new(ext_ptr as UserPtr, 4)
88+
.reader()
89+
.read::<u32>()?;
9490

9591
match ext_type {
9692
uapi::ASAHI_COMPUTE_EXT_TIMESTAMPS => {
9793
let mut ext_user_timestamps: uapi::drm_asahi_cmd_compute_user_timestamps =
9894
Default::default();
9995

10096
// SAFETY: See above
101-
let mut ext_reader = unsafe {
102-
UserSlicePtr::new(
103-
ext_ptr as usize as *mut _,
104-
core::mem::size_of::<uapi::drm_asahi_cmd_compute_user_timestamps>(),
105-
)
106-
.reader()
107-
};
97+
let mut ext_reader = UserSlice::new(
98+
ext_ptr as UserPtr,
99+
core::mem::size_of::<uapi::drm_asahi_cmd_compute_user_timestamps>(),
100+
)
101+
.reader();
108102
// SAFETY: The output buffer is valid and of the correct size, and all bit
109103
// patterns are valid.
110-
unsafe {
111-
ext_reader.read_raw(
112-
&mut ext_user_timestamps as *mut _ as *mut u8,
104+
ext_reader.read_raw(unsafe {
105+
core::slice::from_raw_parts_mut(
106+
&mut ext_user_timestamps as *mut _ as *mut MaybeUninit<u8>,
113107
core::mem::size_of::<uapi::drm_asahi_cmd_compute_user_timestamps>(),
114-
)?;
115-
}
108+
)
109+
})?;
116110

117111
user_timestamps.start = common::get_timestamp_object(
118112
objects,

drivers/gpu/drm/asahi/queue/render.rs

Lines changed: 37 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,15 @@ use crate::util::*;
1616
use crate::workqueue::WorkError;
1717
use crate::{buffer, file, fw, gpu, microseq, workqueue};
1818
use crate::{inner_ptr, inner_weak_ptr};
19+
use core::mem::MaybeUninit;
1920
use core::sync::atomic::Ordering;
2021
use kernel::dma_fence::RawDmaFence;
2122
use kernel::drm::sched::Job;
22-
use kernel::io_buffer::IoBufferReader;
2323
use kernel::new_mutex;
2424
use kernel::prelude::*;
2525
use kernel::sync::Arc;
26+
use kernel::uaccess::{UserPtr, UserSlice};
2627
use kernel::uapi;
27-
use kernel::user_ptr::UserSlicePtr;
2828
use kernel::xarray;
2929

3030
const DEBUG_CLASS: DebugFlags = DebugFlags::Render;
@@ -232,21 +232,19 @@ impl super::QueueInner::ver {
232232

233233
let cmdbuf_read_size =
234234
(cmd.cmd_buffer_size as usize).min(core::mem::size_of::<uapi::drm_asahi_cmd_render>());
235-
// SAFETY: This is the sole UserSlicePtr instance for this cmd_buffer.
236-
let mut cmdbuf_reader = unsafe {
237-
UserSlicePtr::new(
238-
cmd.cmd_buffer as usize as *mut _,
239-
cmd.cmd_buffer_size as usize,
240-
)
241-
.reader()
242-
};
235+
// SAFETY: This is the sole UserSlice instance for this cmd_buffer.
236+
let mut cmdbuf_reader =
237+
UserSlice::new(cmd.cmd_buffer as UserPtr, cmd.cmd_buffer_size as usize).reader();
243238

244239
let mut cmdbuf: uapi::drm_asahi_cmd_render = Default::default();
245240
// SAFETY: The output pointer is valid, and the size does not exceed the type size
246241
// per the min() above, and all bit patterns are valid.
247-
unsafe {
248-
cmdbuf_reader.read_raw(&mut cmdbuf as *mut _ as *mut u8, cmdbuf_read_size)?;
249-
}
242+
cmdbuf_reader.read_raw(unsafe {
243+
core::slice::from_raw_parts_mut(
244+
&mut cmdbuf as *mut _ as *mut MaybeUninit<u8>,
245+
cmdbuf_read_size,
246+
)
247+
})?;
250248

251249
if cmdbuf.flags
252250
& !(uapi::ASAHI_RENDER_NO_CLEAR_PIPELINE_TEXTURES
@@ -282,15 +280,12 @@ impl super::QueueInner::ver {
282280

283281
let mut ext_ptr = cmdbuf.extensions;
284282
while ext_ptr != 0 {
285-
let ext_type = u32::from_ne_bytes(
286-
// SAFETY: There is a double read from userspace here, but there is no TOCTOU
287-
// issue since at worst the extension parse below will read garbage, and
288-
// we do not trust any fields anyway.
289-
unsafe { UserSlicePtr::new(ext_ptr as usize as *mut _, 4) }
290-
.read_all()?
291-
.try_into()
292-
.or(Err(EINVAL))?,
293-
);
283+
// SAFETY: There is a double read from userspace here, but there is no TOCTOU
284+
// issue since at worst the extension parse below will read garbage, and
285+
// we do not trust any fields anyway.
286+
let ext_type = UserSlice::new(ext_ptr as UserPtr, 4)
287+
.reader()
288+
.read::<u32>()?;
294289

295290
match ext_type {
296291
uapi::ASAHI_RENDER_EXT_UNKNOWNS => {
@@ -299,21 +294,19 @@ impl super::QueueInner::ver {
299294
return Err(EINVAL);
300295
}
301296
// SAFETY: See above
302-
let mut ext_reader = unsafe {
303-
UserSlicePtr::new(
304-
ext_ptr as usize as *mut _,
305-
core::mem::size_of::<uapi::drm_asahi_cmd_render_unknowns>(),
306-
)
307-
.reader()
308-
};
297+
let mut ext_reader = UserSlice::new(
298+
ext_ptr as UserPtr,
299+
core::mem::size_of::<uapi::drm_asahi_cmd_render_unknowns>(),
300+
)
301+
.reader();
309302
// SAFETY: The output buffer is valid and of the correct size, and all bit
310303
// patterns are valid.
311-
unsafe {
312-
ext_reader.read_raw(
313-
&mut unks as *mut _ as *mut u8,
304+
ext_reader.read_raw(unsafe {
305+
core::slice::from_raw_parts_mut(
306+
&mut unks as *mut _ as *mut MaybeUninit<u8>,
314307
core::mem::size_of::<uapi::drm_asahi_cmd_render_unknowns>(),
315-
)?;
316-
}
308+
)
309+
})?;
317310

318311
ext_ptr = unks.next;
319312
}
@@ -322,21 +315,19 @@ impl super::QueueInner::ver {
322315
Default::default();
323316

324317
// SAFETY: See above
325-
let mut ext_reader = unsafe {
326-
UserSlicePtr::new(
327-
ext_ptr as usize as *mut _,
328-
core::mem::size_of::<uapi::drm_asahi_cmd_render_user_timestamps>(),
329-
)
330-
.reader()
331-
};
318+
let mut ext_reader = UserSlice::new(
319+
ext_ptr as UserPtr,
320+
core::mem::size_of::<uapi::drm_asahi_cmd_render_user_timestamps>(),
321+
)
322+
.reader();
332323
// SAFETY: The output buffer is valid and of the correct size, and all bit
333324
// patterns are valid.
334-
unsafe {
335-
ext_reader.read_raw(
336-
&mut ext_user_timestamps as *mut _ as *mut u8,
325+
ext_reader.read_raw(unsafe {
326+
core::slice::from_raw_parts_mut(
327+
&mut ext_user_timestamps as *mut _ as *mut MaybeUninit<u8>,
337328
core::mem::size_of::<uapi::drm_asahi_cmd_render_user_timestamps>(),
338-
)?;
339-
}
329+
)
330+
})?;
340331

341332
vtx_user_timestamps.start = common::get_timestamp_object(
342333
objects,

0 commit comments

Comments
 (0)