Skip to content

Commit 1d812e8

Browse files
hoshinolinajannau
authored andcommitted
drm/asahi: Convert to GPUVM and implement more VM_BIND ops
Signed-off-by: Asahi Lina <lina@asahilina.net>
1 parent f7ea137 commit 1d812e8

9 files changed

Lines changed: 572 additions & 272 deletions

File tree

drivers/gpu/drm/asahi/alloc.rs

Lines changed: 26 additions & 26 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.reserve(1, GFP_KERNEL))?;
@@ -874,8 +875,11 @@ impl HeapAllocator {
874875
new_top
875876
);
876877

877-
self.mm
878-
.with_inner(|inner| inner.backing_objects.try_push((obj, gpu_ptr)))?;
878+
self.mm.with_inner(|inner| {
879+
inner
880+
.backing_objects
881+
.push((obj, mapping, gpu_ptr), GFP_KERNEL)
882+
})?;
879883

880884
self.top = new_top;
881885

@@ -896,8 +900,8 @@ impl HeapAllocator {
896900
inner
897901
.backing_objects
898902
.binary_search_by(|obj| {
899-
let start = obj.1;
900-
let end = obj.1 + obj.0.size() as u64;
903+
let start = obj.2;
904+
let end = obj.2 + obj.0.size() as u64;
901905
if start > addr {
902906
Ordering::Greater
903907
} else if end <= addr {
@@ -1013,7 +1017,7 @@ impl Allocator for HeapAllocator {
10131017
let idx = idx.unwrap_or(inner.backing_objects.len() - 1);
10141018
let obj = &mut inner.backing_objects[idx];
10151019
let p = obj.0.vmap()?.as_mut_ptr() as *mut u8;
1016-
Ok((obj.1, obj.0.size(), p))
1020+
Ok((obj.2, obj.0.size(), p))
10171021
})?;
10181022
assert!(obj_start <= start);
10191023
assert!(obj_start + obj_size as u64 >= end);
@@ -1091,10 +1095,6 @@ impl Drop for HeapAllocatorInner {
10911095
&*self.name,
10921096
self.allocated
10931097
);
1094-
} else {
1095-
for mut obj in self.backing_objects.drain(..) {
1096-
obj.0.drop_vm_mappings(self.vm_id);
1097-
}
10981098
}
10991099
}
11001100
}

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: 51 additions & 37 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

@@ -154,16 +160,16 @@ const VM_SHADER_END: u64 = 0x11_ffffffff;
154160
/// Start address of the general user mapping region.
155161
const VM_USER_START: u64 = 0x20_00000000;
156162
/// End address of the general user mapping region.
157-
const VM_USER_END: u64 = 0x5f_ffffffff;
163+
const VM_USER_END: u64 = 0x6f_ffff0000;
158164

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

@@ -298,7 +304,7 @@ impl File {
298304

299305
let gpu = &device.data().gpu;
300306
let file_id = file.inner().id;
301-
let vm = gpu.new_vm(file_id)?;
307+
let vm = gpu.new_vm()?;
302308

303309
let resv = file.inner().vms().reserve()?;
304310
let id: u32 = resv.index().try_into()?;
@@ -343,15 +349,15 @@ impl File {
343349
);
344350
let mut dummy_obj = gem::new_kernel_object(device, 0x4000)?;
345351
dummy_obj.vmap()?.as_mut_slice().fill(0);
346-
dummy_obj.map_at(&vm, VM_UNK_PAGE, mmu::PROT_GPU_SHARED_RW, true)?;
352+
let dummy_mapping = dummy_obj.map_at(&vm, VM_UNK_PAGE, mmu::PROT_GPU_SHARED_RW, true)?;
347353

348354
mod_dev_dbg!(device, "[File {} VM {}]: VM created\n", file_id, id);
349355
resv.store(Box::new(Vm {
350356
ualloc,
351357
ualloc_priv,
352358
vm,
353-
dummy_obj,
354-
})?)?;
359+
_dummy_mapping: dummy_mapping,
360+
}, GFP_KERNEL,)?)?;
355361

356362
data.vm_id = id;
357363

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

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

522518
let start = data.addr;
523519
let end = data.addr + data.range - 1;
@@ -590,11 +586,36 @@ impl File {
590586
.vm
591587
.clone();
592588

593-
bo.map_at(&vm, start, prot, true)?;
589+
vm.bind_object(&bo.gem, data.addr, data.range, data.offset, prot)?;
594590

595591
Ok(0)
596592
}
597593

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

608-
let mut bo = gem::lookup_handle(file, data.handle)?;
629+
let bo = gem::lookup_handle(file, data.handle)?;
609630

610631
if data.vm_id == 0 {
611-
bo.drop_file_mappings(file.inner().id);
632+
Self::unbind_gem_object(file, &bo.gem)?;
612633
} else {
613-
let vm_id = file
614-
.inner()
634+
file.inner()
615635
.vms()
616636
.get(data.vm_id.try_into()?)
617637
.ok_or(ENOENT)?
618638
.borrow()
619639
.vm
620-
.id();
621-
bo.drop_vm_mappings(vm_id);
640+
.drop_mappings(&bo.gem)?;
622641
}
623642

624643
Ok(0)
@@ -828,11 +847,6 @@ impl File {
828847
Ok(_) => Ok(0),
829848
}
830849
}
831-
832-
/// Returns the unique file ID for this `File`.
833-
pub(crate) fn file_id(&self) -> u64 {
834-
self.id
835-
}
836850
}
837851

838852
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)