1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Implementation of the IOMMU SVA API for the ARM SMMUv3
4*4882a593Smuzhiyun */
5*4882a593Smuzhiyun
6*4882a593Smuzhiyun #include <linux/mm.h>
7*4882a593Smuzhiyun #include <linux/mmu_context.h>
8*4882a593Smuzhiyun #include <linux/slab.h>
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #include "arm-smmu-v3.h"
11*4882a593Smuzhiyun #include "../../io-pgtable-arm.h"
12*4882a593Smuzhiyun
13*4882a593Smuzhiyun static DEFINE_MUTEX(sva_lock);
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun /*
16*4882a593Smuzhiyun * Check if the CPU ASID is available on the SMMU side. If a private context
17*4882a593Smuzhiyun * descriptor is using it, try to replace it.
18*4882a593Smuzhiyun */
19*4882a593Smuzhiyun static struct arm_smmu_ctx_desc *
arm_smmu_share_asid(struct mm_struct * mm,u16 asid)20*4882a593Smuzhiyun arm_smmu_share_asid(struct mm_struct *mm, u16 asid)
21*4882a593Smuzhiyun {
22*4882a593Smuzhiyun int ret;
23*4882a593Smuzhiyun u32 new_asid;
24*4882a593Smuzhiyun struct arm_smmu_ctx_desc *cd;
25*4882a593Smuzhiyun struct arm_smmu_device *smmu;
26*4882a593Smuzhiyun struct arm_smmu_domain *smmu_domain;
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun cd = xa_load(&arm_smmu_asid_xa, asid);
29*4882a593Smuzhiyun if (!cd)
30*4882a593Smuzhiyun return NULL;
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun if (cd->mm) {
33*4882a593Smuzhiyun if (WARN_ON(cd->mm != mm))
34*4882a593Smuzhiyun return ERR_PTR(-EINVAL);
35*4882a593Smuzhiyun /* All devices bound to this mm use the same cd struct. */
36*4882a593Smuzhiyun refcount_inc(&cd->refs);
37*4882a593Smuzhiyun return cd;
38*4882a593Smuzhiyun }
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun smmu_domain = container_of(cd, struct arm_smmu_domain, s1_cfg.cd);
41*4882a593Smuzhiyun smmu = smmu_domain->smmu;
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun ret = xa_alloc(&arm_smmu_asid_xa, &new_asid, cd,
44*4882a593Smuzhiyun XA_LIMIT(1, (1 << smmu->asid_bits) - 1), GFP_KERNEL);
45*4882a593Smuzhiyun if (ret)
46*4882a593Smuzhiyun return ERR_PTR(-ENOSPC);
47*4882a593Smuzhiyun /*
48*4882a593Smuzhiyun * Race with unmap: TLB invalidations will start targeting the new ASID,
49*4882a593Smuzhiyun * which isn't assigned yet. We'll do an invalidate-all on the old ASID
50*4882a593Smuzhiyun * later, so it doesn't matter.
51*4882a593Smuzhiyun */
52*4882a593Smuzhiyun cd->asid = new_asid;
53*4882a593Smuzhiyun /*
54*4882a593Smuzhiyun * Update ASID and invalidate CD in all associated masters. There will
55*4882a593Smuzhiyun * be some overlap between use of both ASIDs, until we invalidate the
56*4882a593Smuzhiyun * TLB.
57*4882a593Smuzhiyun */
58*4882a593Smuzhiyun arm_smmu_write_ctx_desc(smmu_domain, 0, cd);
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun /* Invalidate TLB entries previously associated with that context */
61*4882a593Smuzhiyun arm_smmu_tlb_inv_asid(smmu, asid);
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun xa_erase(&arm_smmu_asid_xa, asid);
64*4882a593Smuzhiyun return NULL;
65*4882a593Smuzhiyun }
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun __maybe_unused
arm_smmu_alloc_shared_cd(struct mm_struct * mm)68*4882a593Smuzhiyun static struct arm_smmu_ctx_desc *arm_smmu_alloc_shared_cd(struct mm_struct *mm)
69*4882a593Smuzhiyun {
70*4882a593Smuzhiyun u16 asid;
71*4882a593Smuzhiyun int err = 0;
72*4882a593Smuzhiyun u64 tcr, par, reg;
73*4882a593Smuzhiyun struct arm_smmu_ctx_desc *cd;
74*4882a593Smuzhiyun struct arm_smmu_ctx_desc *ret = NULL;
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun asid = arm64_mm_context_get(mm);
77*4882a593Smuzhiyun if (!asid)
78*4882a593Smuzhiyun return ERR_PTR(-ESRCH);
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun cd = kzalloc(sizeof(*cd), GFP_KERNEL);
81*4882a593Smuzhiyun if (!cd) {
82*4882a593Smuzhiyun err = -ENOMEM;
83*4882a593Smuzhiyun goto out_put_context;
84*4882a593Smuzhiyun }
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun refcount_set(&cd->refs, 1);
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun mutex_lock(&arm_smmu_asid_lock);
89*4882a593Smuzhiyun ret = arm_smmu_share_asid(mm, asid);
90*4882a593Smuzhiyun if (ret) {
91*4882a593Smuzhiyun mutex_unlock(&arm_smmu_asid_lock);
92*4882a593Smuzhiyun goto out_free_cd;
93*4882a593Smuzhiyun }
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun err = xa_insert(&arm_smmu_asid_xa, asid, cd, GFP_KERNEL);
96*4882a593Smuzhiyun mutex_unlock(&arm_smmu_asid_lock);
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun if (err)
99*4882a593Smuzhiyun goto out_free_asid;
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun tcr = FIELD_PREP(CTXDESC_CD_0_TCR_T0SZ, 64ULL - vabits_actual) |
102*4882a593Smuzhiyun FIELD_PREP(CTXDESC_CD_0_TCR_IRGN0, ARM_LPAE_TCR_RGN_WBWA) |
103*4882a593Smuzhiyun FIELD_PREP(CTXDESC_CD_0_TCR_ORGN0, ARM_LPAE_TCR_RGN_WBWA) |
104*4882a593Smuzhiyun FIELD_PREP(CTXDESC_CD_0_TCR_SH0, ARM_LPAE_TCR_SH_IS) |
105*4882a593Smuzhiyun CTXDESC_CD_0_TCR_EPD1 | CTXDESC_CD_0_AA64;
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun switch (PAGE_SIZE) {
108*4882a593Smuzhiyun case SZ_4K:
109*4882a593Smuzhiyun tcr |= FIELD_PREP(CTXDESC_CD_0_TCR_TG0, ARM_LPAE_TCR_TG0_4K);
110*4882a593Smuzhiyun break;
111*4882a593Smuzhiyun case SZ_16K:
112*4882a593Smuzhiyun tcr |= FIELD_PREP(CTXDESC_CD_0_TCR_TG0, ARM_LPAE_TCR_TG0_16K);
113*4882a593Smuzhiyun break;
114*4882a593Smuzhiyun case SZ_64K:
115*4882a593Smuzhiyun tcr |= FIELD_PREP(CTXDESC_CD_0_TCR_TG0, ARM_LPAE_TCR_TG0_64K);
116*4882a593Smuzhiyun break;
117*4882a593Smuzhiyun default:
118*4882a593Smuzhiyun WARN_ON(1);
119*4882a593Smuzhiyun err = -EINVAL;
120*4882a593Smuzhiyun goto out_free_asid;
121*4882a593Smuzhiyun }
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun reg = read_sanitised_ftr_reg(SYS_ID_AA64MMFR0_EL1);
124*4882a593Smuzhiyun par = cpuid_feature_extract_unsigned_field(reg, ID_AA64MMFR0_PARANGE_SHIFT);
125*4882a593Smuzhiyun tcr |= FIELD_PREP(CTXDESC_CD_0_TCR_IPS, par);
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun cd->ttbr = virt_to_phys(mm->pgd);
128*4882a593Smuzhiyun cd->tcr = tcr;
129*4882a593Smuzhiyun /*
130*4882a593Smuzhiyun * MAIR value is pretty much constant and global, so we can just get it
131*4882a593Smuzhiyun * from the current CPU register
132*4882a593Smuzhiyun */
133*4882a593Smuzhiyun cd->mair = read_sysreg(mair_el1);
134*4882a593Smuzhiyun cd->asid = asid;
135*4882a593Smuzhiyun cd->mm = mm;
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun return cd;
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun out_free_asid:
140*4882a593Smuzhiyun arm_smmu_free_asid(cd);
141*4882a593Smuzhiyun out_free_cd:
142*4882a593Smuzhiyun kfree(cd);
143*4882a593Smuzhiyun out_put_context:
144*4882a593Smuzhiyun arm64_mm_context_put(mm);
145*4882a593Smuzhiyun return err < 0 ? ERR_PTR(err) : ret;
146*4882a593Smuzhiyun }
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun __maybe_unused
arm_smmu_free_shared_cd(struct arm_smmu_ctx_desc * cd)149*4882a593Smuzhiyun static void arm_smmu_free_shared_cd(struct arm_smmu_ctx_desc *cd)
150*4882a593Smuzhiyun {
151*4882a593Smuzhiyun if (arm_smmu_free_asid(cd)) {
152*4882a593Smuzhiyun /* Unpin ASID */
153*4882a593Smuzhiyun arm64_mm_context_put(cd->mm);
154*4882a593Smuzhiyun kfree(cd);
155*4882a593Smuzhiyun }
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun
arm_smmu_sva_supported(struct arm_smmu_device * smmu)158*4882a593Smuzhiyun bool arm_smmu_sva_supported(struct arm_smmu_device *smmu)
159*4882a593Smuzhiyun {
160*4882a593Smuzhiyun unsigned long reg, fld;
161*4882a593Smuzhiyun unsigned long oas;
162*4882a593Smuzhiyun unsigned long asid_bits;
163*4882a593Smuzhiyun u32 feat_mask = ARM_SMMU_FEAT_BTM | ARM_SMMU_FEAT_COHERENCY;
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun if (vabits_actual == 52)
166*4882a593Smuzhiyun feat_mask |= ARM_SMMU_FEAT_VAX;
167*4882a593Smuzhiyun
168*4882a593Smuzhiyun if ((smmu->features & feat_mask) != feat_mask)
169*4882a593Smuzhiyun return false;
170*4882a593Smuzhiyun
171*4882a593Smuzhiyun if (!(smmu->pgsize_bitmap & PAGE_SIZE))
172*4882a593Smuzhiyun return false;
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun /*
175*4882a593Smuzhiyun * Get the smallest PA size of all CPUs (sanitized by cpufeature). We're
176*4882a593Smuzhiyun * not even pretending to support AArch32 here. Abort if the MMU outputs
177*4882a593Smuzhiyun * addresses larger than what we support.
178*4882a593Smuzhiyun */
179*4882a593Smuzhiyun reg = read_sanitised_ftr_reg(SYS_ID_AA64MMFR0_EL1);
180*4882a593Smuzhiyun fld = cpuid_feature_extract_unsigned_field(reg, ID_AA64MMFR0_PARANGE_SHIFT);
181*4882a593Smuzhiyun oas = id_aa64mmfr0_parange_to_phys_shift(fld);
182*4882a593Smuzhiyun if (smmu->oas < oas)
183*4882a593Smuzhiyun return false;
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun /* We can support bigger ASIDs than the CPU, but not smaller */
186*4882a593Smuzhiyun fld = cpuid_feature_extract_unsigned_field(reg, ID_AA64MMFR0_ASID_SHIFT);
187*4882a593Smuzhiyun asid_bits = fld ? 16 : 8;
188*4882a593Smuzhiyun if (smmu->asid_bits < asid_bits)
189*4882a593Smuzhiyun return false;
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun /*
192*4882a593Smuzhiyun * See max_pinned_asids in arch/arm64/mm/context.c. The following is
193*4882a593Smuzhiyun * generally the maximum number of bindable processes.
194*4882a593Smuzhiyun */
195*4882a593Smuzhiyun if (arm64_kernel_unmapped_at_el0())
196*4882a593Smuzhiyun asid_bits--;
197*4882a593Smuzhiyun dev_dbg(smmu->dev, "%d shared contexts\n", (1 << asid_bits) -
198*4882a593Smuzhiyun num_possible_cpus() - 2);
199*4882a593Smuzhiyun
200*4882a593Smuzhiyun return true;
201*4882a593Smuzhiyun }
202*4882a593Smuzhiyun
arm_smmu_iopf_supported(struct arm_smmu_master * master)203*4882a593Smuzhiyun static bool arm_smmu_iopf_supported(struct arm_smmu_master *master)
204*4882a593Smuzhiyun {
205*4882a593Smuzhiyun return false;
206*4882a593Smuzhiyun }
207*4882a593Smuzhiyun
arm_smmu_master_sva_supported(struct arm_smmu_master * master)208*4882a593Smuzhiyun bool arm_smmu_master_sva_supported(struct arm_smmu_master *master)
209*4882a593Smuzhiyun {
210*4882a593Smuzhiyun if (!(master->smmu->features & ARM_SMMU_FEAT_SVA))
211*4882a593Smuzhiyun return false;
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun /* SSID and IOPF support are mandatory for the moment */
214*4882a593Smuzhiyun return master->ssid_bits && arm_smmu_iopf_supported(master);
215*4882a593Smuzhiyun }
216*4882a593Smuzhiyun
arm_smmu_master_sva_enabled(struct arm_smmu_master * master)217*4882a593Smuzhiyun bool arm_smmu_master_sva_enabled(struct arm_smmu_master *master)
218*4882a593Smuzhiyun {
219*4882a593Smuzhiyun bool enabled;
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun mutex_lock(&sva_lock);
222*4882a593Smuzhiyun enabled = master->sva_enabled;
223*4882a593Smuzhiyun mutex_unlock(&sva_lock);
224*4882a593Smuzhiyun return enabled;
225*4882a593Smuzhiyun }
226*4882a593Smuzhiyun
arm_smmu_master_enable_sva(struct arm_smmu_master * master)227*4882a593Smuzhiyun int arm_smmu_master_enable_sva(struct arm_smmu_master *master)
228*4882a593Smuzhiyun {
229*4882a593Smuzhiyun mutex_lock(&sva_lock);
230*4882a593Smuzhiyun master->sva_enabled = true;
231*4882a593Smuzhiyun mutex_unlock(&sva_lock);
232*4882a593Smuzhiyun
233*4882a593Smuzhiyun return 0;
234*4882a593Smuzhiyun }
235*4882a593Smuzhiyun
arm_smmu_master_disable_sva(struct arm_smmu_master * master)236*4882a593Smuzhiyun int arm_smmu_master_disable_sva(struct arm_smmu_master *master)
237*4882a593Smuzhiyun {
238*4882a593Smuzhiyun mutex_lock(&sva_lock);
239*4882a593Smuzhiyun if (!list_empty(&master->bonds)) {
240*4882a593Smuzhiyun dev_err(master->dev, "cannot disable SVA, device is bound\n");
241*4882a593Smuzhiyun mutex_unlock(&sva_lock);
242*4882a593Smuzhiyun return -EBUSY;
243*4882a593Smuzhiyun }
244*4882a593Smuzhiyun master->sva_enabled = false;
245*4882a593Smuzhiyun mutex_unlock(&sva_lock);
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun return 0;
248*4882a593Smuzhiyun }
249