Skip to content

Commit 93b390c

Browse files
committed
drm/asahi: Convert to GPUVM and implement more VM_BIND ops
Signed-off-by: Asahi Lina <lina@asahilina.net>
1 parent e885c48 commit 93b390c

9 files changed

Lines changed: 564 additions & 270 deletions

File tree

drivers/gpu/drm/asahi/alloc.rs

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,7 @@ pub(crate) struct SimpleAllocation {
444444
ptr: Option<NonNull<u8>>,
445445
gpu_ptr: u64,
446446
size: usize,
447-
vm: mmu::Vm,
447+
_mapping: mmu::KernelMapping,
448448
obj: crate::gem::ObjectRef,
449449
}
450450

@@ -464,7 +464,6 @@ impl Drop for SimpleAllocation {
464464
vmap.as_mut_slice().fill(0x42);
465465
}
466466
}
467-
self.obj.drop_vm_mappings(self.vm.id());
468467
}
469468
}
470469

@@ -566,7 +565,7 @@ impl Allocator for SimpleAllocator {
566565
if debug_enabled(DebugFlags::FillAllocations) {
567566
obj.vmap()?.as_mut_slice().fill(0xde);
568567
}
569-
let iova = obj.map_into_range(
568+
let mapping = obj.map_into_range(
570569
&self.vm,
571570
self.start,
572571
self.end,
@@ -575,6 +574,8 @@ impl Allocator for SimpleAllocator {
575574
true,
576575
)?;
577576

577+
let iova = mapping.iova();
578+
578579
let ptr = unsafe { p.add(offset) };
579580
let gpu_ptr = (iova + offset) as u64;
580581

@@ -592,7 +593,7 @@ impl Allocator for SimpleAllocator {
592593
ptr: NonNull::new(ptr),
593594
gpu_ptr,
594595
size,
595-
vm: self.vm.clone(),
596+
_mapping: mapping,
596597
obj,
597598
})
598599
}
@@ -696,11 +697,10 @@ impl RawAllocation for HeapAllocation {
696697
struct HeapAllocatorInner {
697698
dev: AsahiDevRef,
698699
allocated: usize,
699-
backing_objects: Vec<(crate::gem::ObjectRef, u64)>,
700+
backing_objects: Vec<(crate::gem::ObjectRef, mmu::KernelMapping, u64)>,
700701
garbage: Option<Vec<mm::Node<HeapAllocatorInner, HeapAllocationInner>>>,
701702
total_garbage: usize,
702703
name: CString,
703-
vm_id: u64,
704704
}
705705

706706
/// A heap allocator which uses the DRM MM range allocator to manage its objects.
@@ -754,7 +754,6 @@ impl HeapAllocator {
754754
backing_objects: Vec::new(),
755755
// TODO: This clearly needs a try_clone() or similar
756756
name: CString::try_from_fmt(fmt!("{}", &*name))?,
757-
vm_id: vm.id(),
758757
garbage: if keep_garbage { Some(Vec::new()) } else { None },
759758
total_garbage: 0,
760759
};
@@ -817,16 +816,18 @@ impl HeapAllocator {
817816
}
818817

819818
let gpu_ptr = self.top;
820-
if let Err(e) = obj.map_at(&self.vm, gpu_ptr, self.prot, self.cpu_maps) {
821-
dev_err!(
822-
&self.dev,
823-
"HeapAllocator[{}]::add_block: Failed to map at {:#x} ({:?})\n",
824-
&*self.name,
825-
gpu_ptr,
826-
e
827-
);
828-
return Err(e);
829-
}
819+
let mapping = obj
820+
.map_at(&self.vm, gpu_ptr, self.prot, self.cpu_maps)
821+
.map_err(|err| {
822+
dev_err!(
823+
&self.dev,
824+
"HeapAllocator[{}]::add_block: Failed to map at {:#x} ({:?})\n",
825+
&*self.name,
826+
gpu_ptr,
827+
err
828+
);
829+
err
830+
})?;
830831

831832
self.mm
832833
.with_inner(|inner| inner.backing_objects.try_reserve(1))?;
@@ -875,7 +876,7 @@ impl HeapAllocator {
875876
);
876877

877878
self.mm
878-
.with_inner(|inner| inner.backing_objects.try_push((obj, gpu_ptr)))?;
879+
.with_inner(|inner| inner.backing_objects.try_push((obj, mapping, gpu_ptr)))?;
879880

880881
self.top = new_top;
881882

@@ -896,8 +897,8 @@ impl HeapAllocator {
896897
inner
897898
.backing_objects
898899
.binary_search_by(|obj| {
899-
let start = obj.1;
900-
let end = obj.1 + obj.0.size() as u64;
900+
let start = obj.2;
901+
let end = obj.2 + obj.0.size() as u64;
901902
if start > addr {
902903
Ordering::Greater
903904
} else if end <= addr {
@@ -1013,7 +1014,7 @@ impl Allocator for HeapAllocator {
10131014
let idx = idx.unwrap_or(inner.backing_objects.len() - 1);
10141015
let obj = &mut inner.backing_objects[idx];
10151016
let p = obj.0.vmap()?.as_mut_ptr() as *mut u8;
1016-
Ok((obj.1, obj.0.size(), p))
1017+
Ok((obj.2, obj.0.size(), p))
10171018
})?;
10181019
assert!(obj_start <= start);
10191020
assert!(obj_start + obj_size as u64 >= end);
@@ -1091,10 +1092,6 @@ impl Drop for HeapAllocatorInner {
10911092
&*self.name,
10921093
self.allocated
10931094
);
1094-
} else {
1095-
for mut obj in self.backing_objects.drain(..) {
1096-
obj.0.drop_vm_mappings(self.vm_id);
1097-
}
10981095
}
10991096
}
11001097
}

drivers/gpu/drm/asahi/driver.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,11 @@ impl drv::Driver for AsahiDriver {
5252
type Object = gem::Object;
5353

5454
const INFO: drv::DriverInfo = INFO;
55-
const FEATURES: u32 =
56-
drv::FEAT_GEM | drv::FEAT_RENDER | drv::FEAT_SYNCOBJ | drv::FEAT_SYNCOBJ_TIMELINE;
55+
const FEATURES: u32 = drv::FEAT_GEM
56+
| drv::FEAT_RENDER
57+
| drv::FEAT_SYNCOBJ
58+
| drv::FEAT_SYNCOBJ_TIMELINE
59+
| drv::FEAT_GEM_GPUVA;
5760

5861
kernel::declare_drm_ioctls! {
5962
(ASAHI_GET_PARAMS, drm_asahi_get_params,

drivers/gpu/drm/asahi/file.rs

Lines changed: 50 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,19 @@ struct Vm {
3030
ualloc: Arc<Mutex<alloc::DefaultAllocator>>,
3131
ualloc_priv: Arc<Mutex<alloc::DefaultAllocator>>,
3232
vm: mmu::Vm,
33-
dummy_obj: gem::ObjectRef,
33+
_dummy_mapping: mmu::KernelMapping,
3434
}
3535

3636
impl Drop for Vm {
3737
fn drop(&mut self) {
38-
// Mappings create a reference loop, make sure to break it.
39-
self.dummy_obj.drop_vm_mappings(self.vm.id());
38+
// When the user Vm is dropped, unmap everything in the user range
39+
if self
40+
.vm
41+
.unmap_range(mmu::IOVA_USER_BASE as u64, VM_USER_END)
42+
.is_err()
43+
{
44+
pr_err!("Vm::Drop: vm.unmap_range() failed\n");
45+
}
4046
}
4147
}
4248

@@ -156,16 +162,16 @@ const VM_SHADER_END: u64 = 0x11_ffffffff;
156162
/// Start address of the general user mapping region.
157163
const VM_USER_START: u64 = 0x20_00000000;
158164
/// End address of the general user mapping region.
159-
const VM_USER_END: u64 = 0x5f_ffffffff;
165+
const VM_USER_END: u64 = 0x6f_ffff0000;
160166

161167
/// Start address of the kernel-managed GPU-only mapping region.
162-
const VM_DRV_GPU_START: u64 = 0x60_00000000;
168+
const VM_DRV_GPU_START: u64 = 0x70_00000000;
163169
/// End address of the kernel-managed GPU-only mapping region.
164-
const VM_DRV_GPU_END: u64 = 0x60_ffffffff;
170+
const VM_DRV_GPU_END: u64 = 0x70_ffffffff;
165171
/// Start address of the kernel-managed GPU/FW shared mapping region.
166-
const VM_DRV_GPUFW_START: u64 = 0x61_00000000;
172+
const VM_DRV_GPUFW_START: u64 = 0x71_00000000;
167173
/// End address of the kernel-managed GPU/FW shared mapping region.
168-
const VM_DRV_GPUFW_END: u64 = 0x61_ffffffff;
174+
const VM_DRV_GPUFW_END: u64 = 0x71_ffffffff;
169175
/// Address of a special dummy page?
170176
const VM_UNK_PAGE: u64 = 0x6f_ffff8000;
171177

@@ -297,7 +303,7 @@ impl File {
297303

298304
let gpu = &device.data().gpu;
299305
let file_id = file.inner().id;
300-
let vm = gpu.new_vm(file_id)?;
306+
let vm = gpu.new_vm()?;
301307

302308
let resv = file.inner().vms().reserve()?;
303309
let id: u32 = resv.index().try_into()?;
@@ -342,14 +348,14 @@ impl File {
342348
);
343349
let mut dummy_obj = gem::new_kernel_object(device, 0x4000)?;
344350
dummy_obj.vmap()?.as_mut_slice().fill(0);
345-
dummy_obj.map_at(&vm, VM_UNK_PAGE, mmu::PROT_GPU_SHARED_RW, true)?;
351+
let dummy_mapping = dummy_obj.map_at(&vm, VM_UNK_PAGE, mmu::PROT_GPU_SHARED_RW, true)?;
346352

347353
mod_dev_dbg!(device, "[File {} VM {}]: VM created\n", file_id, id);
348354
resv.store(Box::try_new(Vm {
349355
ualloc,
350356
ualloc_priv,
351357
vm,
352-
dummy_obj,
358+
_dummy_mapping: dummy_mapping,
353359
})?)?;
354360

355361
data.vm_id = id;
@@ -491,15 +497,10 @@ impl File {
491497
data: &mut uapi::drm_asahi_gem_bind,
492498
file: &DrmFile,
493499
) -> Result<u32> {
494-
if data.offset != 0 {
495-
pr_err!("gem_bind: Offset not supported yet\n");
496-
return Err(EINVAL); // Not supported yet
497-
}
498-
499-
if (data.addr | data.range) as usize & mmu::UAT_PGMSK != 0 {
500+
if (data.addr | data.range | data.offset) as usize & mmu::UAT_PGMSK != 0 {
500501
cls_pr_debug!(
501502
Errors,
502-
"gem_bind: Addr/range not page aligned: {:#x} {:#x}\n",
503+
"gem_bind: Addr/range/offset not page aligned: {:#x} {:#x}\n",
503504
data.addr,
504505
data.range
505506
);
@@ -511,12 +512,7 @@ impl File {
511512
return Err(EINVAL);
512513
}
513514

514-
let mut bo = gem::lookup_handle(file, data.handle)?;
515-
516-
if data.range != bo.size().try_into()? {
517-
pr_err!("gem_bind: Partial maps not supported yet\n");
518-
return Err(EINVAL); // Not supported yet
519-
}
515+
let bo = gem::lookup_handle(file, data.handle)?;
520516

521517
let start = data.addr;
522518
let end = data.addr + data.range - 1;
@@ -589,11 +585,36 @@ impl File {
589585
.vm
590586
.clone();
591587

592-
bo.map_at(&vm, start, prot, true)?;
588+
vm.bind_object(&bo.gem, data.addr, data.range, data.offset, prot)?;
593589

594590
Ok(0)
595591
}
596592

593+
pub(crate) fn unbind_gem_object(file: &DrmFile, bo: &gem::Object) -> Result {
594+
let mut index = 0;
595+
loop {
596+
let item = file
597+
.inner()
598+
.vms()
599+
.find(index, xarray::XArray::<Box<Vm>>::MAX);
600+
match item {
601+
Some((idx, file_vm)) => {
602+
// Clone since we can't hold the xarray spinlock while
603+
// calling drop_mappings()
604+
let vm = file_vm.borrow().vm.clone();
605+
core::mem::drop(file_vm);
606+
vm.drop_mappings(bo)?;
607+
if idx == xarray::XArray::<Box<Vm>>::MAX {
608+
break;
609+
}
610+
index = idx + 1;
611+
}
612+
None => break,
613+
}
614+
}
615+
Ok(())
616+
}
617+
597618
pub(crate) fn do_gem_unbind_all(
598619
_device: &AsahiDevice,
599620
data: &mut uapi::drm_asahi_gem_bind,
@@ -604,20 +625,18 @@ impl File {
604625
return Err(EINVAL);
605626
}
606627

607-
let mut bo = gem::lookup_handle(file, data.handle)?;
628+
let bo = gem::lookup_handle(file, data.handle)?;
608629

609630
if data.vm_id == 0 {
610-
bo.drop_file_mappings(file.inner().id);
631+
Self::unbind_gem_object(file, &bo.gem)?;
611632
} else {
612-
let vm_id = file
613-
.inner()
633+
file.inner()
614634
.vms()
615635
.get(data.vm_id.try_into()?)
616636
.ok_or(ENOENT)?
617637
.borrow()
618638
.vm
619-
.id();
620-
bo.drop_vm_mappings(vm_id);
639+
.drop_mappings(&bo.gem)?;
621640
}
622641

623642
Ok(0)
@@ -827,11 +846,6 @@ impl File {
827846
Ok(_) => Ok(0),
828847
}
829848
}
830-
831-
/// Returns the unique file ID for this `File`.
832-
pub(crate) fn file_id(&self) -> u64 {
833-
self.id
834-
}
835849
}
836850

837851
impl Drop for File {

drivers/gpu/drm/asahi/fw/initdata.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
55
use super::channels;
66
use super::types::*;
7-
use crate::{default_zeroed, gem, no_debug, trivial_gpustruct};
7+
use crate::{default_zeroed, gem, mmu, no_debug, trivial_gpustruct};
88

99
pub(crate) mod raw {
1010
use super::*;
@@ -1326,6 +1326,8 @@ pub(crate) struct RuntimePointers {
13261326
pub(crate) unkptr_1c8: GpuArray<u8>,
13271327

13281328
pub(crate) buffer_mgr_ctl: gem::ObjectRef,
1329+
pub(crate) buffer_mgr_ctl_low_mapping: Option<mmu::KernelMapping>,
1330+
pub(crate) buffer_mgr_ctl_high_mapping: Option<mmu::KernelMapping>,
13291331
}
13301332

13311333
#[versions(AGX)]

0 commit comments

Comments
 (0)