On Sun, 18 Feb 2024 22:41:21 +0100 Boris Brezillon <boris.brezillon@xxxxxxxxxxxxx> wrote: > +int panthor_vm_active(struct panthor_vm *vm) > +{ > + struct panthor_device *ptdev = vm->ptdev; > + struct io_pgtable_cfg *cfg = &io_pgtable_ops_to_pgtable(vm->pgtbl_ops)->cfg; > + int ret = 0, as, cookie; > + u64 transtab, transcfg; > + > + if (!drm_dev_enter(&ptdev->base, &cookie)) > + return -ENODEV; > + > + if (refcount_inc_not_zero(&vm->as.active_cnt)) > + goto out_dev_exit; > + > + mutex_lock(&ptdev->mmu->as.slots_lock); > + > + if (refcount_inc_not_zero(&vm->as.active_cnt)) > + goto out_unlock; > + > + as = vm->as.id; > + if (as >= 0) { > + /* Unhandled pagefault on this AS, the MMU was disabled. We need to > + * re-enable the MMU after clearing+unmasking the AS interrupts. > + */ > + if (ptdev->mmu->as.faulty_mask & panthor_mmu_as_fault_mask(ptdev, as)) > + goto out_enable_as; > + > + goto out_make_active; > + } > + > + /* Check for a free AS */ > + if (vm->for_mcu) { > + drm_WARN_ON(&ptdev->base, ptdev->mmu->as.alloc_mask & BIT(0)); > + as = 0; > + } else { > + as = ffz(ptdev->mmu->as.alloc_mask | BIT(0)); > + } > + > + if (!(BIT(as) & ptdev->gpu_info.as_present)) { > + struct panthor_vm *lru_vm; > + > + lru_vm = list_first_entry_or_null(&ptdev->mmu->as.lru_list, > + struct panthor_vm, > + as.lru_node); > + if (drm_WARN_ON(&ptdev->base, !lru_vm)) { > + ret = -EBUSY; > + goto out_unlock; > + } > + > + drm_WARN_ON(&ptdev->base, refcount_read(&lru_vm->as.active_cnt)); > + as = lru_vm->as.id; > + panthor_vm_release_as_locked(lru_vm); > + } > + > + /* Assign the free or reclaimed AS to the FD */ > + vm->as.id = as; > + set_bit(as, &ptdev->mmu->as.alloc_mask); > + ptdev->mmu->as.slots[as].vm = vm; > + > +out_enable_as: > + transtab = cfg->arm_lpae_s1_cfg.ttbr; > + transcfg = AS_TRANSCFG_PTW_MEMATTR_WB | > + AS_TRANSCFG_PTW_RA | > + AS_TRANSCFG_ADRMODE_AARCH64_4K; We also need AS_TRANSCFG_INA_BITS(55 - va_bits); otherwise we lack one page table level on 32-bit platforms where the virtual address space is artificially limited to 32bits. > + if (ptdev->coherent) > + transcfg |= AS_TRANSCFG_PTW_SH_OS; > + > + /* If the VM is re-activated, we clear the fault. */ > + vm->unhandled_fault = false; > + > + /* Unhandled pagefault on this AS, clear the fault and re-enable interrupts > + * before enabling the AS. > + */ > + if (ptdev->mmu->as.faulty_mask & panthor_mmu_as_fault_mask(ptdev, as)) { > + gpu_write(ptdev, MMU_INT_CLEAR, panthor_mmu_as_fault_mask(ptdev, as)); > + ptdev->mmu->as.faulty_mask &= ~panthor_mmu_as_fault_mask(ptdev, as); > + gpu_write(ptdev, MMU_INT_MASK, ~ptdev->mmu->as.faulty_mask); > + } > + > + ret = panthor_mmu_as_enable(vm->ptdev, vm->as.id, transtab, transcfg, vm->memattr); > + > +out_make_active: > + if (!ret) { > + refcount_set(&vm->as.active_cnt, 1); > + list_del_init(&vm->as.lru_node); > + } > + > +out_unlock: > + mutex_unlock(&ptdev->mmu->as.slots_lock); > + > +out_dev_exit: > + drm_dev_exit(cookie); > + return ret; > +}