Skip to content

Commit 22f3e5c

Browse files
committed
drm/asahi: file: Update to newer VM_BIND API
Signed-off-by: Asahi Lina <lina@asahilina.net>
1 parent 9fa0fc8 commit 22f3e5c

File tree

4 files changed

+97
-86
lines changed

4 files changed

+97
-86
lines changed

drivers/gpu/drm/asahi/file.rs

Lines changed: 71 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@
99
1010
use crate::debug::*;
1111
use crate::driver::AsahiDevice;
12-
use crate::{alloc, buffer, driver, gem, mmu, queue};
12+
use crate::{alloc, buffer, driver, gem, mmu, queue, util::RangeExt};
1313
use core::mem::MaybeUninit;
14+
use core::ops::Range;
1415
use kernel::dma_fence::RawDmaFence;
1516
use kernel::drm::gem::BaseObject;
1617
use kernel::error::code::*;
@@ -30,16 +31,29 @@ struct Vm {
3031
ualloc: Arc<Mutex<alloc::DefaultAllocator>>,
3132
ualloc_priv: Arc<Mutex<alloc::DefaultAllocator>>,
3233
vm: mmu::Vm,
34+
kernel_range: Range<u64>,
3335
_dummy_mapping: mmu::KernelMapping,
3436
}
3537

3638
impl Drop for Vm {
3739
fn drop(&mut self) {
3840
// When the user Vm is dropped, unmap everything in the user range
39-
if self
40-
.vm
41-
.unmap_range(mmu::IOVA_USER_BASE, VM_USER_END)
42-
.is_err()
41+
let left_range = VM_USER_RANGE.start..self.kernel_range.start;
42+
let right_range = self.kernel_range.end..VM_USER_RANGE.end;
43+
44+
if !left_range.is_empty()
45+
&& self
46+
.vm
47+
.unmap_range(left_range.start, left_range.range())
48+
.is_err()
49+
{
50+
pr_err!("Vm::Drop: vm.unmap_range() failed\n");
51+
}
52+
if !right_range.is_empty()
53+
&& self
54+
.vm
55+
.unmap_range(right_range.start, right_range.range())
56+
.is_err()
4357
{
4458
pr_err!("Vm::Drop: vm.unmap_range() failed\n");
4559
}
@@ -155,23 +169,11 @@ pub(crate) struct File {
155169
/// Convenience type alias for our DRM `File` type.
156170
pub(crate) type DrmFile = drm::file::File<File>;
157171

158-
/// Start address of the 32-bit USC address space.
159-
const VM_SHADER_START: u64 = 0x11_00000000;
160-
/// End address of the 32-bit USC address space.
161-
const VM_SHADER_END: u64 = 0x11_ffffffff;
162-
/// Start address of the general user mapping region.
163-
const VM_USER_START: u64 = 0x20_00000000;
164-
/// End address of the general user mapping region.
165-
const VM_USER_END: u64 = 0x6f_ffff0000;
166-
167-
/// Start address of the kernel-managed GPU-only mapping region.
168-
const VM_DRV_GPU_START: u64 = 0x70_00000000;
169-
/// End address of the kernel-managed GPU-only mapping region.
170-
const VM_DRV_GPU_END: u64 = 0x70_ffffffff;
171-
/// Start address of the kernel-managed GPU/FW shared mapping region.
172-
const VM_DRV_GPUFW_START: u64 = 0x71_00000000;
173-
/// End address of the kernel-managed GPU/FW shared mapping region.
174-
const VM_DRV_GPUFW_END: u64 = 0x71_ffffffff;
172+
/// Available VM range for the user
173+
const VM_USER_RANGE: Range<u64> = mmu::IOVA_USER_USABLE_RANGE;
174+
175+
/// Minimum reserved AS for kernel mappings
176+
const VM_KERNEL_MIN_SIZE: u64 = 0x20000000;
175177

176178
impl drm::file::DriverFile for File {
177179
type Driver = driver::AsahiDriver;
@@ -247,10 +249,11 @@ impl File {
247249

248250
vm_page_size: mmu::UAT_PGSZ as u32,
249251
pad1: 0,
250-
vm_user_start: VM_USER_START,
251-
vm_user_end: VM_USER_END,
252-
vm_shader_start: VM_SHADER_START,
253-
vm_shader_end: VM_SHADER_END,
252+
vm_user_start: VM_USER_RANGE.start,
253+
vm_user_end: VM_USER_RANGE.end,
254+
vm_usc_start: 0, // Arbitrary
255+
vm_usc_end: 0,
256+
vm_kernel_min_size: VM_KERNEL_MIN_SIZE,
254257

255258
max_syncs_per_submission: 0,
256259
max_commands_per_submission: MAX_COMMANDS_PER_SUBMISSION,
@@ -299,9 +302,25 @@ impl File {
299302
return Err(EINVAL);
300303
}
301304

305+
let kernel_range = data.kernel_start..data.kernel_end;
306+
307+
// Validate requested kernel range
308+
if !VM_USER_RANGE.is_superset(kernel_range.clone())
309+
|| kernel_range.range() < VM_KERNEL_MIN_SIZE
310+
|| kernel_range.start & (mmu::UAT_PGMSK as u64) != 0
311+
|| kernel_range.end & (mmu::UAT_PGMSK as u64) != 0
312+
{
313+
cls_pr_debug!(Errors, "vm_create: Invalid kernel range\n");
314+
return Err(EINVAL);
315+
}
316+
317+
let kernel_half_size = (kernel_range.range() >> 1) & !(mmu::UAT_PGMSK as u64);
318+
let kernel_gpu_range = kernel_range.start..(kernel_range.start + kernel_half_size);
319+
let kernel_gpufw_range = kernel_gpu_range.end..kernel_range.end;
320+
302321
let gpu = &device.data().gpu;
303322
let file_id = file.inner().id;
304-
let vm = gpu.new_vm()?;
323+
let vm = gpu.new_vm(kernel_range.clone())?;
305324

306325
let resv = file.inner().vms().reserve()?;
307326
let id: u32 = resv.index().try_into()?;
@@ -316,7 +335,7 @@ impl File {
316335
let ualloc = Arc::pin_init(Mutex::new(alloc::DefaultAllocator::new(
317336
device,
318337
&vm,
319-
VM_DRV_GPU_START..VM_DRV_GPU_END,
338+
kernel_gpu_range,
320339
buffer::PAGE_SIZE,
321340
mmu::PROT_GPU_SHARED_RW,
322341
512 * 1024,
@@ -327,7 +346,7 @@ impl File {
327346
let ualloc_priv = Arc::pin_init(Mutex::new(alloc::DefaultAllocator::new(
328347
device,
329348
&vm,
330-
VM_DRV_GPUFW_START..VM_DRV_GPUFW_END,
349+
kernel_gpufw_range,
331350
buffer::PAGE_SIZE,
332351
mmu::PROT_GPU_FW_PRIV_RW,
333352
64 * 1024,
@@ -352,6 +371,7 @@ impl File {
352371
ualloc,
353372
ualloc_priv,
354373
vm,
374+
kernel_range,
355375
_dummy_mapping: dummy_mapping,
356376
})?)?;
357377

@@ -512,47 +532,17 @@ impl File {
512532
let bo = gem::lookup_handle(file, data.handle)?;
513533

514534
let start = data.addr;
515-
let end = data.addr + data.range - 1;
516-
517-
if (VM_SHADER_START..=VM_SHADER_END).contains(&start) {
518-
if !(VM_SHADER_START..=VM_SHADER_END).contains(&end) {
519-
cls_pr_debug!(
520-
Errors,
521-
"gem_bind: Invalid map range {:#x}..{:#x} (straddles shader range)\n",
522-
start,
523-
end
524-
);
525-
return Err(EINVAL); // Invalid map range
526-
}
527-
} else if (VM_USER_START..=VM_USER_END).contains(&start) {
528-
if !(VM_USER_START..=VM_USER_END).contains(&end) {
529-
cls_pr_debug!(
530-
Errors,
531-
"gem_bind: Invalid map range {:#x}..{:#x} (straddles user range)\n",
532-
start,
533-
end
534-
);
535-
return Err(EINVAL); // Invalid map range
536-
}
537-
} else {
538-
cls_pr_debug!(
539-
Errors,
540-
"gem_bind: Invalid map range {:#x}..{:#x}\n",
541-
start,
542-
end
543-
);
544-
return Err(EINVAL); // Invalid map range
545-
}
535+
let end = data.addr.checked_add(data.range).ok_or(EINVAL)?;
536+
let range = start..end;
546537

547-
// Just in case
548-
if end >= VM_DRV_GPU_START {
538+
if !VM_USER_RANGE.is_superset(range.clone()) {
549539
cls_pr_debug!(
550540
Errors,
551-
"gem_bind: Invalid map range {:#x}..{:#x} (intrudes in kernel range)\n",
541+
"gem_bind: Invalid map range {:#x}..{:#x} (not contained in user range)\n",
552542
start,
553543
end
554544
);
555-
return Err(EINVAL);
545+
return Err(EINVAL); // Invalid map range
556546
}
557547

558548
let prot = if data.flags & uapi::ASAHI_BIND_READ != 0 {
@@ -572,15 +562,26 @@ impl File {
572562
return Err(EINVAL); // Must specify one of ASAHI_BIND_{READ,WRITE}
573563
};
574564

575-
// Clone it immediately so we aren't holding the XArray lock
576-
let vm = file
565+
let guard = file
577566
.inner()
578567
.vms()
579568
.get(data.vm_id.try_into()?)
580-
.ok_or(ENOENT)?
581-
.borrow()
582-
.vm
583-
.clone();
569+
.ok_or(ENOENT)?;
570+
571+
// Clone it immediately so we aren't holding the XArray lock
572+
let vm = guard.borrow().vm.clone();
573+
let kernel_range = guard.borrow().kernel_range.clone();
574+
core::mem::drop(guard);
575+
576+
if kernel_range.overlaps(range) {
577+
cls_pr_debug!(
578+
Errors,
579+
"gem_bind: Invalid map range {:#x}..{:#x} (intrudes in kernel range)\n",
580+
start,
581+
end
582+
);
583+
return Err(EINVAL);
584+
}
584585

585586
vm.bind_object(&bo.gem, data.addr, data.range, data.offset, prot)?;
586587

drivers/gpu/drm/asahi/gpu.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ pub(crate) trait GpuManager: Send + Sync {
229229
/// Get a reference to the KernelAllocators.
230230
fn alloc(&self) -> Guard<'_, KernelAllocators, MutexBackend>;
231231
/// Create a new `Vm` given a unique `File` ID.
232-
fn new_vm(&self) -> Result<mmu::Vm>;
232+
fn new_vm(&self, kernel_range: Range<u64>) -> Result<mmu::Vm>;
233233
/// Bind a `Vm` to an available slot and return the `VmBind`.
234234
fn bind_vm(&self, vm: &mmu::Vm) -> Result<mmu::VmBind>;
235235
/// Create a new user command queue.
@@ -1164,8 +1164,8 @@ impl GpuManager for GpuManager::ver {
11641164
guard
11651165
}
11661166

1167-
fn new_vm(&self) -> Result<mmu::Vm> {
1168-
self.uat.new_vm(self.ids.vm.next())
1167+
fn new_vm(&self, kernel_range: Range<u64>) -> Result<mmu::Vm> {
1168+
self.uat.new_vm(self.ids.vm.next(), kernel_range)
11691169
}
11701170

11711171
fn bind_vm(&self, vm: &mmu::Vm) -> Result<mmu::VmBind> {

drivers/gpu/drm/asahi/mmu.rs

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ const PTE_TABLE: u64 = 0x3; // BIT(0) | BIT(1)
9090
/// Address of a special dummy page?
9191
//const IOVA_UNK_PAGE: u64 = 0x6f_ffff8000;
9292
pub(crate) const IOVA_UNK_PAGE: u64 = IOVA_USER_TOP - 2 * UAT_PGSZ as u64;
93+
/// User VA range excluding the unk page
94+
pub(crate) const IOVA_USER_USABLE_RANGE: Range<u64> = IOVA_USER_BASE..IOVA_UNK_PAGE;
9395

9496
// KernelMapping protection types
9597

@@ -998,6 +1000,7 @@ impl Vm {
9981000
fn new(
9991001
dev: &driver::AsahiDevice,
10001002
uat_inner: Arc<UatInner>,
1003+
kernel_range: Range<u64>,
10011004
cfg: &'static hw::HwConfig,
10021005
is_kernel: bool,
10031006
id: u64,
@@ -1015,10 +1018,10 @@ impl Vm {
10151018
},
10161019
(),
10171020
)?;
1018-
let va_range = if is_kernel {
1019-
IOVA_KERN_RANGE
1021+
let (va_range, gpuvm_range) = if is_kernel {
1022+
(IOVA_KERN_RANGE, kernel_range.clone())
10201023
} else {
1021-
IOVA_USER_RANGE
1024+
(IOVA_USER_RANGE, IOVA_USER_USABLE_RANGE)
10221025
};
10231026

10241027
let mm = mm::Allocator::new(va_range.start, va_range.range(), ())?;
@@ -1040,8 +1043,8 @@ impl Vm {
10401043
c_str!("Asahi::GpuVm"),
10411044
dev,
10421045
&*(dummy_obj.gem),
1043-
va_range.clone(),
1044-
0..0,
1046+
gpuvm_range,
1047+
kernel_range,
10451048
init!(VmInner {
10461049
dev: dev.into(),
10471050
va_range,
@@ -1479,8 +1482,15 @@ impl Uat {
14791482
}
14801483

14811484
/// Creates a new `Vm` linked to this UAT.
1482-
pub(crate) fn new_vm(&self, id: u64) -> Result<Vm> {
1483-
Vm::new(&self.dev, self.inner.clone(), self.cfg, false, id)
1485+
pub(crate) fn new_vm(&self, id: u64, kernel_range: Range<u64>) -> Result<Vm> {
1486+
Vm::new(
1487+
&self.dev,
1488+
self.inner.clone(),
1489+
kernel_range,
1490+
self.cfg,
1491+
false,
1492+
id,
1493+
)
14841494
}
14851495

14861496
/// Creates the reference-counted inner data for a new `Uat` instance.
@@ -1523,8 +1533,8 @@ impl Uat {
15231533
let pagetables_rgn = Self::map_region(dev, c_str!("pagetables"), PAGETABLES_SIZE, true)?;
15241534

15251535
dev_info!(dev, "MMU: Creating kernel page tables\n");
1526-
let kernel_lower_vm = Vm::new(dev, inner.clone(), cfg, false, 1)?;
1527-
let kernel_vm = Vm::new(dev, inner.clone(), cfg, true, 0)?;
1536+
let kernel_lower_vm = Vm::new(dev, inner.clone(), IOVA_USER_RANGE, cfg, false, 1)?;
1537+
let kernel_vm = Vm::new(dev, inner.clone(), IOVA_KERN_RANGE, cfg, true, 0)?;
15281538

15291539
dev_info!(dev, "MMU: Kernel page tables created\n");
15301540

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -839,7 +839,7 @@ impl super::Queue::ver {
839839
tile_config: U64(tile_config),
840840
aux_fb: inner.aux_fb.gpu_pointer(),
841841
unk_108: Default::default(),
842-
pipeline_base: U64(0x11_00000000),
842+
pipeline_base: U64(cmdbuf.fragment_usc_base),
843843
unk_140: U64(unks.frg_unk_140),
844844
helper_program: cmdbuf.fragment_helper_program,
845845
unk_14c: 0,
@@ -944,7 +944,7 @@ impl super::Queue::ver {
944944
r.add(0x11829, cmdbuf.fragment_helper_arg);
945945
r.add(0x11f79, cmdbuf.fragment_helper_cfg.into());
946946
r.add(0x15359, 0);
947-
r.add(0x10069, 0x11_00000000); // USC_EXEC_BASE_ISP
947+
r.add(0x10069, cmdbuf.fragment_usc_base); // USC_EXEC_BASE_ISP
948948
r.add(0x16020, 0);
949949
r.add(0x16461, inner.aux_fb.gpu_pointer().into());
950950
r.add(0x16090, inner.aux_fb.gpu_pointer().into());
@@ -1341,7 +1341,7 @@ impl super::Queue::ver {
13411341
#[ver(G < G14)]
13421342
unk_ac: unks.tiling_control_2 as u32, // fixed
13431343
unk_b0: Default::default(), // fixed
1344-
pipeline_base: U64(0x11_00000000),
1344+
pipeline_base: U64(cmdbuf.vertex_usc_base),
13451345
#[ver(G < G14)]
13461346
tvb_cluster_meta4: inner
13471347
.scene
@@ -1433,7 +1433,7 @@ impl super::Queue::ver {
14331433
r.add(0x1c1a9, 0); // 0x10151 bit 1 enables
14341434
r.add(0x1c1b1, 0);
14351435
r.add(0x1c1b9, 0);
1436-
r.add(0x10061, 0x11_00000000); // USC_EXEC_BASE_TA
1436+
r.add(0x10061, cmdbuf.vertex_usc_base); // USC_EXEC_BASE_TA
14371437
r.add(0x11801, cmdbuf.vertex_helper_program.into());
14381438
r.add(0x11809, cmdbuf.vertex_helper_arg);
14391439
r.add(0x11f71, cmdbuf.vertex_helper_cfg.into());

0 commit comments

Comments
 (0)