Skip to content

Commit

Permalink
drm/asahi: file: Update to newer VM_BIND API
Browse files Browse the repository at this point in the history
Signed-off-by: Asahi Lina <lina@asahilina.net>
  • Loading branch information
asahilina committed May 10, 2024
1 parent 9fa0fc8 commit 1213cf2
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 88 deletions.
141 changes: 71 additions & 70 deletions drivers/gpu/drm/asahi/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@

use crate::debug::*;
use crate::driver::AsahiDevice;
use crate::{alloc, buffer, driver, gem, mmu, queue};
use crate::{alloc, buffer, driver, gem, mmu, queue, util::RangeExt};
use core::mem::MaybeUninit;
use core::ops::Range;
use kernel::dma_fence::RawDmaFence;
use kernel::drm::gem::BaseObject;
use kernel::error::code::*;
Expand All @@ -30,16 +31,29 @@ struct Vm {
ualloc: Arc<Mutex<alloc::DefaultAllocator>>,
ualloc_priv: Arc<Mutex<alloc::DefaultAllocator>>,
vm: mmu::Vm,
kernel_range: Range<u64>,
_dummy_mapping: mmu::KernelMapping,
}

impl Drop for Vm {
fn drop(&mut self) {
// When the user Vm is dropped, unmap everything in the user range
if self
.vm
.unmap_range(mmu::IOVA_USER_BASE, VM_USER_END)
.is_err()
let left_range = VM_USER_RANGE.start..self.kernel_range.start;
let right_range = self.kernel_range.end..VM_USER_RANGE.end;

if !left_range.is_empty()
&& self
.vm
.unmap_range(left_range.start, left_range.range())
.is_err()
{
pr_err!("Vm::Drop: vm.unmap_range() failed\n");
}
if !right_range.is_empty()
&& self
.vm
.unmap_range(right_range.start, right_range.range())
.is_err()
{
pr_err!("Vm::Drop: vm.unmap_range() failed\n");
}
Expand Down Expand Up @@ -155,23 +169,11 @@ pub(crate) struct File {
/// Convenience type alias for our DRM `File` type.
pub(crate) type DrmFile = drm::file::File<File>;

/// Start address of the 32-bit USC address space.
const VM_SHADER_START: u64 = 0x11_00000000;
/// End address of the 32-bit USC address space.
const VM_SHADER_END: u64 = 0x11_ffffffff;
/// Start address of the general user mapping region.
const VM_USER_START: u64 = 0x20_00000000;
/// End address of the general user mapping region.
const VM_USER_END: u64 = 0x6f_ffff0000;

/// Start address of the kernel-managed GPU-only mapping region.
const VM_DRV_GPU_START: u64 = 0x70_00000000;
/// End address of the kernel-managed GPU-only mapping region.
const VM_DRV_GPU_END: u64 = 0x70_ffffffff;
/// Start address of the kernel-managed GPU/FW shared mapping region.
const VM_DRV_GPUFW_START: u64 = 0x71_00000000;
/// End address of the kernel-managed GPU/FW shared mapping region.
const VM_DRV_GPUFW_END: u64 = 0x71_ffffffff;
/// Available VM range for the user
const VM_USER_RANGE: Range<u64> = mmu::IOVA_USER_USABLE_RANGE;

/// Minimum reserved AS for kernel mappings
const VM_KERNEL_MIN_SIZE: u64 = 0x20000000;

impl drm::file::DriverFile for File {
type Driver = driver::AsahiDriver;
Expand Down Expand Up @@ -247,10 +249,11 @@ impl File {

vm_page_size: mmu::UAT_PGSZ as u32,
pad1: 0,
vm_user_start: VM_USER_START,
vm_user_end: VM_USER_END,
vm_shader_start: VM_SHADER_START,
vm_shader_end: VM_SHADER_END,
vm_user_start: VM_USER_RANGE.start,
vm_user_end: VM_USER_RANGE.end,
vm_usc_start: 0, // Arbitrary
vm_usc_end: 0,
vm_kernel_min_size: VM_KERNEL_MIN_SIZE,

max_syncs_per_submission: 0,
max_commands_per_submission: MAX_COMMANDS_PER_SUBMISSION,
Expand Down Expand Up @@ -299,9 +302,25 @@ impl File {
return Err(EINVAL);
}

let kernel_range = data.kernel_start..data.kernel_end;

// Validate requested kernel range
if !VM_USER_RANGE.is_superset(kernel_range.clone())
|| kernel_range.range() < VM_KERNEL_MIN_SIZE
|| kernel_range.start & (mmu::UAT_PGMSK as u64) != 0
|| kernel_range.end & (mmu::UAT_PGMSK as u64) != 0
{
cls_pr_debug!(Errors, "vm_create: Invalid kernel range\n");
return Err(EINVAL);
}

let kernel_half_size = (kernel_range.range() >> 1) & !(mmu::UAT_PGMSK as u64);
let kernel_gpu_range = kernel_range.start..(kernel_range.start + kernel_half_size);
let kernel_gpufw_range = kernel_gpu_range.end..kernel_range.end;

let gpu = &device.data().gpu;
let file_id = file.inner().id;
let vm = gpu.new_vm()?;
let vm = gpu.new_vm(kernel_range.clone())?;

let resv = file.inner().vms().reserve()?;
let id: u32 = resv.index().try_into()?;
Expand All @@ -316,7 +335,7 @@ impl File {
let ualloc = Arc::pin_init(Mutex::new(alloc::DefaultAllocator::new(
device,
&vm,
VM_DRV_GPU_START..VM_DRV_GPU_END,
kernel_gpu_range,
buffer::PAGE_SIZE,
mmu::PROT_GPU_SHARED_RW,
512 * 1024,
Expand All @@ -327,7 +346,7 @@ impl File {
let ualloc_priv = Arc::pin_init(Mutex::new(alloc::DefaultAllocator::new(
device,
&vm,
VM_DRV_GPUFW_START..VM_DRV_GPUFW_END,
kernel_gpufw_range,
buffer::PAGE_SIZE,
mmu::PROT_GPU_FW_PRIV_RW,
64 * 1024,
Expand All @@ -352,6 +371,7 @@ impl File {
ualloc,
ualloc_priv,
vm,
kernel_range,
_dummy_mapping: dummy_mapping,
})?)?;

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

let start = data.addr;
let end = data.addr + data.range - 1;

if (VM_SHADER_START..=VM_SHADER_END).contains(&start) {
if !(VM_SHADER_START..=VM_SHADER_END).contains(&end) {
cls_pr_debug!(
Errors,
"gem_bind: Invalid map range {:#x}..{:#x} (straddles shader range)\n",
start,
end
);
return Err(EINVAL); // Invalid map range
}
} else if (VM_USER_START..=VM_USER_END).contains(&start) {
if !(VM_USER_START..=VM_USER_END).contains(&end) {
cls_pr_debug!(
Errors,
"gem_bind: Invalid map range {:#x}..{:#x} (straddles user range)\n",
start,
end
);
return Err(EINVAL); // Invalid map range
}
} else {
cls_pr_debug!(
Errors,
"gem_bind: Invalid map range {:#x}..{:#x}\n",
start,
end
);
return Err(EINVAL); // Invalid map range
}
let end = data.addr.checked_add(data.range).ok_or(EINVAL)?;
let range = start..end;

// Just in case
if end >= VM_DRV_GPU_START {
if !VM_USER_RANGE.is_superset(range.clone()) {
cls_pr_debug!(
Errors,
"gem_bind: Invalid map range {:#x}..{:#x} (intrudes in kernel range)\n",
"gem_bind: Invalid map range {:#x}..{:#x} (not contained in user range)\n",
start,
end
);
return Err(EINVAL);
return Err(EINVAL); // Invalid map range
}

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

// Clone it immediately so we aren't holding the XArray lock
let vm = file
let guard = file
.inner()
.vms()
.get(data.vm_id.try_into()?)
.ok_or(ENOENT)?
.borrow()
.vm
.clone();
.ok_or(ENOENT)?;

// Clone it immediately so we aren't holding the XArray lock
let vm = guard.borrow().vm.clone();
let kernel_range = guard.borrow().kernel_range.clone();
core::mem::drop(guard);

if kernel_range.overlaps(range) {
cls_pr_debug!(
Errors,
"gem_bind: Invalid map range {:#x}..{:#x} (intrudes in kernel range)\n",
start,
end
);
return Err(EINVAL);
}

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

Expand Down
6 changes: 3 additions & 3 deletions drivers/gpu/drm/asahi/gpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ pub(crate) trait GpuManager: Send + Sync {
/// Get a reference to the KernelAllocators.
fn alloc(&self) -> Guard<'_, KernelAllocators, MutexBackend>;
/// Create a new `Vm` given a unique `File` ID.
fn new_vm(&self) -> Result<mmu::Vm>;
fn new_vm(&self, kernel_range: Range<u64>) -> Result<mmu::Vm>;
/// Bind a `Vm` to an available slot and return the `VmBind`.
fn bind_vm(&self, vm: &mmu::Vm) -> Result<mmu::VmBind>;
/// Create a new user command queue.
Expand Down Expand Up @@ -1164,8 +1164,8 @@ impl GpuManager for GpuManager::ver {
guard
}

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

fn bind_vm(&self, vm: &mmu::Vm) -> Result<mmu::VmBind> {
Expand Down
28 changes: 19 additions & 9 deletions drivers/gpu/drm/asahi/mmu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ const PTE_TABLE: u64 = 0x3; // BIT(0) | BIT(1)
/// Address of a special dummy page?
//const IOVA_UNK_PAGE: u64 = 0x6f_ffff8000;
pub(crate) const IOVA_UNK_PAGE: u64 = IOVA_USER_TOP - 2 * UAT_PGSZ as u64;
/// User VA range excluding the unk page
pub(crate) const IOVA_USER_USABLE_RANGE: Range<u64> = IOVA_USER_BASE..IOVA_UNK_PAGE;

// KernelMapping protection types

Expand Down Expand Up @@ -998,6 +1000,7 @@ impl Vm {
fn new(
dev: &driver::AsahiDevice,
uat_inner: Arc<UatInner>,
kernel_range: Range<u64>,
cfg: &'static hw::HwConfig,
is_kernel: bool,
id: u64,
Expand All @@ -1015,10 +1018,10 @@ impl Vm {
},
(),
)?;
let va_range = if is_kernel {
IOVA_KERN_RANGE
let (va_range, gpuvm_range) = if is_kernel {
(IOVA_KERN_RANGE, kernel_range.clone())
} else {
IOVA_USER_RANGE
(IOVA_USER_RANGE, IOVA_USER_USABLE_RANGE)
};

let mm = mm::Allocator::new(va_range.start, va_range.range(), ())?;
Expand All @@ -1040,8 +1043,8 @@ impl Vm {
c_str!("Asahi::GpuVm"),
dev,
&*(dummy_obj.gem),
va_range.clone(),
0..0,
gpuvm_range,
kernel_range,
init!(VmInner {
dev: dev.into(),
va_range,
Expand Down Expand Up @@ -1479,8 +1482,15 @@ impl Uat {
}

/// Creates a new `Vm` linked to this UAT.
pub(crate) fn new_vm(&self, id: u64) -> Result<Vm> {
Vm::new(&self.dev, self.inner.clone(), self.cfg, false, id)
pub(crate) fn new_vm(&self, id: u64, kernel_range: Range<u64>) -> Result<Vm> {
Vm::new(
&self.dev,
self.inner.clone(),
kernel_range,
self.cfg,
false,
id,
)
}

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

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

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

Expand Down
4 changes: 2 additions & 2 deletions drivers/gpu/drm/asahi/queue/compute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ impl super::Queue::ver {
preempt_buf3: inner.preempt_buf.gpu_offset_pointer(preempt3_off),
preempt_buf4: inner.preempt_buf.gpu_offset_pointer(preempt4_off),
preempt_buf5: inner.preempt_buf.gpu_offset_pointer(preempt5_off),
pipeline_base: U64(0x11_00000000),
pipeline_base: U64(cmdbuf.usc_base),
unk_38: U64(0x8c60),
helper_program: cmdbuf.helper_program, // Internal program addr | 1
unk_44: 0,
Expand All @@ -306,7 +306,7 @@ impl super::Queue::ver {
r.add(0x1a4d8, inner.preempt_buf.gpu_offset_pointer(preempt3_off).into());
r.add(0x1a4e0, inner.preempt_buf.gpu_offset_pointer(preempt4_off).into());
r.add(0x1a4e8, inner.preempt_buf.gpu_offset_pointer(preempt5_off).into());
r.add(0x10071, 0x1100000000); // USC_EXEC_BASE_CP
r.add(0x10071, cmdbuf.usc_base); // USC_EXEC_BASE_CP
r.add(0x11841, cmdbuf.helper_program.into());
r.add(0x11849, cmdbuf.helper_arg);
r.add(0x11f81, cmdbuf.helper_cfg.into());
Expand Down
8 changes: 4 additions & 4 deletions drivers/gpu/drm/asahi/queue/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -839,7 +839,7 @@ impl super::Queue::ver {
tile_config: U64(tile_config),
aux_fb: inner.aux_fb.gpu_pointer(),
unk_108: Default::default(),
pipeline_base: U64(0x11_00000000),
pipeline_base: U64(cmdbuf.fragment_usc_base),
unk_140: U64(unks.frg_unk_140),
helper_program: cmdbuf.fragment_helper_program,
unk_14c: 0,
Expand Down Expand Up @@ -944,7 +944,7 @@ impl super::Queue::ver {
r.add(0x11829, cmdbuf.fragment_helper_arg);
r.add(0x11f79, cmdbuf.fragment_helper_cfg.into());
r.add(0x15359, 0);
r.add(0x10069, 0x11_00000000); // USC_EXEC_BASE_ISP
r.add(0x10069, cmdbuf.fragment_usc_base); // USC_EXEC_BASE_ISP
r.add(0x16020, 0);
r.add(0x16461, inner.aux_fb.gpu_pointer().into());
r.add(0x16090, inner.aux_fb.gpu_pointer().into());
Expand Down Expand Up @@ -1341,7 +1341,7 @@ impl super::Queue::ver {
#[ver(G < G14)]
unk_ac: unks.tiling_control_2 as u32, // fixed
unk_b0: Default::default(), // fixed
pipeline_base: U64(0x11_00000000),
pipeline_base: U64(cmdbuf.vertex_usc_base),
#[ver(G < G14)]
tvb_cluster_meta4: inner
.scene
Expand Down Expand Up @@ -1433,7 +1433,7 @@ impl super::Queue::ver {
r.add(0x1c1a9, 0); // 0x10151 bit 1 enables
r.add(0x1c1b1, 0);
r.add(0x1c1b9, 0);
r.add(0x10061, 0x11_00000000); // USC_EXEC_BASE_TA
r.add(0x10061, cmdbuf.vertex_usc_base); // USC_EXEC_BASE_TA
r.add(0x11801, cmdbuf.vertex_helper_program.into());
r.add(0x11809, cmdbuf.vertex_helper_arg);
r.add(0x11f71, cmdbuf.vertex_helper_cfg.into());
Expand Down

0 comments on commit 1213cf2

Please sign in to comment.