Skip to content

Commit d525b0a

Browse files
robclarkwilldeacon
authored andcommitted
iommu/arm-smmu: Pretty-print context fault related regs
Parse out the bitfields for easier-to-read fault messages. Signed-off-by: Rob Clark <[email protected]> Reviewed-by: Pranjal Shrivastava <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Will Deacon <[email protected]>
1 parent 5508978 commit d525b0a

File tree

3 files changed

+92
-51
lines changed

3 files changed

+92
-51
lines changed

drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c

Lines changed: 16 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -383,64 +383,44 @@ irqreturn_t qcom_smmu_context_fault(int irq, void *dev)
383383
struct arm_smmu_domain *smmu_domain = dev;
384384
struct io_pgtable_ops *ops = smmu_domain->pgtbl_ops;
385385
struct arm_smmu_device *smmu = smmu_domain->smmu;
386-
u32 fsr, fsynr, cbfrsynra, resume = 0;
386+
struct arm_smmu_context_fault_info cfi;
387+
u32 resume = 0;
387388
int idx = smmu_domain->cfg.cbndx;
388389
phys_addr_t phys_soft;
389-
unsigned long iova;
390390
int ret, tmp;
391391

392392
static DEFINE_RATELIMIT_STATE(_rs,
393393
DEFAULT_RATELIMIT_INTERVAL,
394394
DEFAULT_RATELIMIT_BURST);
395395

396-
fsr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSR);
397-
if (!(fsr & ARM_SMMU_CB_FSR_FAULT))
398-
return IRQ_NONE;
396+
arm_smmu_read_context_fault_info(smmu, idx, &cfi);
399397

400-
fsynr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSYNR0);
401-
iova = arm_smmu_cb_readq(smmu, idx, ARM_SMMU_CB_FAR);
402-
cbfrsynra = arm_smmu_gr1_read(smmu, ARM_SMMU_GR1_CBFRSYNRA(idx));
398+
if (!(cfi.fsr & ARM_SMMU_CB_FSR_FAULT))
399+
return IRQ_NONE;
403400

404401
if (list_empty(&tbu_list)) {
405-
ret = report_iommu_fault(&smmu_domain->domain, NULL, iova,
406-
fsynr & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
402+
ret = report_iommu_fault(&smmu_domain->domain, NULL, cfi.iova,
403+
cfi.fsynr & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
407404

408405
if (ret == -ENOSYS)
409-
dev_err_ratelimited(smmu->dev,
410-
"Unhandled context fault: fsr=0x%x, iova=0x%08lx, fsynr=0x%x, cbfrsynra=0x%x, cb=%d\n",
411-
fsr, iova, fsynr, cbfrsynra, idx);
406+
arm_smmu_print_context_fault_info(smmu, idx, &cfi);
412407

413-
arm_smmu_cb_write(smmu, idx, ARM_SMMU_CB_FSR, fsr);
408+
arm_smmu_cb_write(smmu, idx, ARM_SMMU_CB_FSR, cfi.fsr);
414409
return IRQ_HANDLED;
415410
}
416411

417-
phys_soft = ops->iova_to_phys(ops, iova);
412+
phys_soft = ops->iova_to_phys(ops, cfi.iova);
418413

419-
tmp = report_iommu_fault(&smmu_domain->domain, NULL, iova,
420-
fsynr & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
414+
tmp = report_iommu_fault(&smmu_domain->domain, NULL, cfi.iova,
415+
cfi.fsynr & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
421416
if (!tmp || tmp == -EBUSY) {
422417
ret = IRQ_HANDLED;
423418
resume = ARM_SMMU_RESUME_TERMINATE;
424419
} else {
425-
phys_addr_t phys_atos = qcom_smmu_verify_fault(smmu_domain, iova, fsr);
420+
phys_addr_t phys_atos = qcom_smmu_verify_fault(smmu_domain, cfi.iova, cfi.fsr);
426421

427422
if (__ratelimit(&_rs)) {
428-
dev_err(smmu->dev,
429-
"Unhandled context fault: fsr=0x%x, iova=0x%08lx, fsynr=0x%x, cbfrsynra=0x%x, cb=%d\n",
430-
fsr, iova, fsynr, cbfrsynra, idx);
431-
dev_err(smmu->dev,
432-
"FSR = %08x [%s%s%s%s%s%s%s%s%s], SID=0x%x\n",
433-
fsr,
434-
(fsr & 0x02) ? "TF " : "",
435-
(fsr & 0x04) ? "AFF " : "",
436-
(fsr & 0x08) ? "PF " : "",
437-
(fsr & 0x10) ? "EF " : "",
438-
(fsr & 0x20) ? "TLBMCF " : "",
439-
(fsr & 0x40) ? "TLBLKF " : "",
440-
(fsr & 0x80) ? "MHF " : "",
441-
(fsr & 0x40000000) ? "SS " : "",
442-
(fsr & 0x80000000) ? "MULTI " : "",
443-
cbfrsynra);
423+
arm_smmu_print_context_fault_info(smmu, idx, &cfi);
444424

445425
dev_err(smmu->dev,
446426
"soft iova-to-phys=%pa\n", &phys_soft);
@@ -474,10 +454,10 @@ irqreturn_t qcom_smmu_context_fault(int irq, void *dev)
474454
*/
475455
if (tmp != -EBUSY) {
476456
/* Clear the faulting FSR */
477-
arm_smmu_cb_write(smmu, idx, ARM_SMMU_CB_FSR, fsr);
457+
arm_smmu_cb_write(smmu, idx, ARM_SMMU_CB_FSR, cfi.fsr);
478458

479459
/* Retry or terminate any stalled transactions */
480-
if (fsr & ARM_SMMU_CB_FSR_SS)
460+
if (cfi.fsr & ARM_SMMU_CB_FSR_SS)
481461
arm_smmu_cb_write(smmu, idx, ARM_SMMU_CB_RESUME, resume);
482462
}
483463

drivers/iommu/arm/arm-smmu/arm-smmu.c

Lines changed: 55 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -405,32 +405,72 @@ static const struct iommu_flush_ops arm_smmu_s2_tlb_ops_v1 = {
405405
.tlb_add_page = arm_smmu_tlb_add_page_s2_v1,
406406
};
407407

408+
409+
void arm_smmu_read_context_fault_info(struct arm_smmu_device *smmu, int idx,
410+
struct arm_smmu_context_fault_info *cfi)
411+
{
412+
cfi->iova = arm_smmu_cb_readq(smmu, idx, ARM_SMMU_CB_FAR);
413+
cfi->fsr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSR);
414+
cfi->fsynr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSYNR0);
415+
cfi->cbfrsynra = arm_smmu_gr1_read(smmu, ARM_SMMU_GR1_CBFRSYNRA(idx));
416+
}
417+
418+
void arm_smmu_print_context_fault_info(struct arm_smmu_device *smmu, int idx,
419+
const struct arm_smmu_context_fault_info *cfi)
420+
{
421+
dev_dbg(smmu->dev,
422+
"Unhandled context fault: fsr=0x%x, iova=0x%08lx, fsynr=0x%x, cbfrsynra=0x%x, cb=%d\n",
423+
cfi->fsr, cfi->iova, cfi->fsynr, cfi->cbfrsynra, idx);
424+
425+
dev_err(smmu->dev, "FSR = %08x [%s%sFormat=%u%s%s%s%s%s%s%s%s], SID=0x%x\n",
426+
cfi->fsr,
427+
(cfi->fsr & ARM_SMMU_CB_FSR_MULTI) ? "MULTI " : "",
428+
(cfi->fsr & ARM_SMMU_CB_FSR_SS) ? "SS " : "",
429+
(u32)FIELD_GET(ARM_SMMU_CB_FSR_FORMAT, cfi->fsr),
430+
(cfi->fsr & ARM_SMMU_CB_FSR_UUT) ? " UUT" : "",
431+
(cfi->fsr & ARM_SMMU_CB_FSR_ASF) ? " ASF" : "",
432+
(cfi->fsr & ARM_SMMU_CB_FSR_TLBLKF) ? " TLBLKF" : "",
433+
(cfi->fsr & ARM_SMMU_CB_FSR_TLBMCF) ? " TLBMCF" : "",
434+
(cfi->fsr & ARM_SMMU_CB_FSR_EF) ? " EF" : "",
435+
(cfi->fsr & ARM_SMMU_CB_FSR_PF) ? " PF" : "",
436+
(cfi->fsr & ARM_SMMU_CB_FSR_AFF) ? " AFF" : "",
437+
(cfi->fsr & ARM_SMMU_CB_FSR_TF) ? " TF" : "",
438+
cfi->cbfrsynra);
439+
440+
dev_err(smmu->dev, "FSYNR0 = %08x [S1CBNDX=%u%s%s%s%s%s%s PLVL=%u]\n",
441+
cfi->fsynr,
442+
(u32)FIELD_GET(ARM_SMMU_CB_FSYNR0_S1CBNDX, cfi->fsynr),
443+
(cfi->fsynr & ARM_SMMU_CB_FSYNR0_AFR) ? " AFR" : "",
444+
(cfi->fsynr & ARM_SMMU_CB_FSYNR0_PTWF) ? " PTWF" : "",
445+
(cfi->fsynr & ARM_SMMU_CB_FSYNR0_NSATTR) ? " NSATTR" : "",
446+
(cfi->fsynr & ARM_SMMU_CB_FSYNR0_IND) ? " IND" : "",
447+
(cfi->fsynr & ARM_SMMU_CB_FSYNR0_PNU) ? " PNU" : "",
448+
(cfi->fsynr & ARM_SMMU_CB_FSYNR0_WNR) ? " WNR" : "",
449+
(u32)FIELD_GET(ARM_SMMU_CB_FSYNR0_PLVL, cfi->fsynr));
450+
}
451+
408452
static irqreturn_t arm_smmu_context_fault(int irq, void *dev)
409453
{
410-
u32 fsr, fsynr, cbfrsynra;
411-
unsigned long iova;
454+
struct arm_smmu_context_fault_info cfi;
412455
struct arm_smmu_domain *smmu_domain = dev;
413456
struct arm_smmu_device *smmu = smmu_domain->smmu;
457+
static DEFINE_RATELIMIT_STATE(rs, DEFAULT_RATELIMIT_INTERVAL,
458+
DEFAULT_RATELIMIT_BURST);
414459
int idx = smmu_domain->cfg.cbndx;
415460
int ret;
416461

417-
fsr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSR);
418-
if (!(fsr & ARM_SMMU_CB_FSR_FAULT))
419-
return IRQ_NONE;
462+
arm_smmu_read_context_fault_info(smmu, idx, &cfi);
420463

421-
fsynr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSYNR0);
422-
iova = arm_smmu_cb_readq(smmu, idx, ARM_SMMU_CB_FAR);
423-
cbfrsynra = arm_smmu_gr1_read(smmu, ARM_SMMU_GR1_CBFRSYNRA(idx));
464+
if (!(cfi.fsr & ARM_SMMU_CB_FSR_FAULT))
465+
return IRQ_NONE;
424466

425-
ret = report_iommu_fault(&smmu_domain->domain, NULL, iova,
426-
fsynr & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
467+
ret = report_iommu_fault(&smmu_domain->domain, NULL, cfi.iova,
468+
cfi.fsynr & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
427469

428-
if (ret == -ENOSYS)
429-
dev_err_ratelimited(smmu->dev,
430-
"Unhandled context fault: fsr=0x%x, iova=0x%08lx, fsynr=0x%x, cbfrsynra=0x%x, cb=%d\n",
431-
fsr, iova, fsynr, cbfrsynra, idx);
470+
if (ret == -ENOSYS && __ratelimit(&rs))
471+
arm_smmu_print_context_fault_info(smmu, idx, &cfi);
432472

433-
arm_smmu_cb_write(smmu, idx, ARM_SMMU_CB_FSR, fsr);
473+
arm_smmu_cb_write(smmu, idx, ARM_SMMU_CB_FSR, cfi.fsr);
434474
return IRQ_HANDLED;
435475
}
436476

drivers/iommu/arm/arm-smmu/arm-smmu.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@ enum arm_smmu_cbar_type {
198198
#define ARM_SMMU_CB_FSR 0x58
199199
#define ARM_SMMU_CB_FSR_MULTI BIT(31)
200200
#define ARM_SMMU_CB_FSR_SS BIT(30)
201+
#define ARM_SMMU_CB_FSR_FORMAT GENMASK(10, 9)
201202
#define ARM_SMMU_CB_FSR_UUT BIT(8)
202203
#define ARM_SMMU_CB_FSR_ASF BIT(7)
203204
#define ARM_SMMU_CB_FSR_TLBLKF BIT(6)
@@ -223,7 +224,14 @@ enum arm_smmu_cbar_type {
223224
#define ARM_SMMU_CB_FAR 0x60
224225

225226
#define ARM_SMMU_CB_FSYNR0 0x68
227+
#define ARM_SMMU_CB_FSYNR0_PLVL GENMASK(1, 0)
226228
#define ARM_SMMU_CB_FSYNR0_WNR BIT(4)
229+
#define ARM_SMMU_CB_FSYNR0_PNU BIT(5)
230+
#define ARM_SMMU_CB_FSYNR0_IND BIT(6)
231+
#define ARM_SMMU_CB_FSYNR0_NSATTR BIT(8)
232+
#define ARM_SMMU_CB_FSYNR0_PTWF BIT(10)
233+
#define ARM_SMMU_CB_FSYNR0_AFR BIT(11)
234+
#define ARM_SMMU_CB_FSYNR0_S1CBNDX GENMASK(23, 16)
227235

228236
#define ARM_SMMU_CB_FSYNR1 0x6c
229237

@@ -533,4 +541,17 @@ struct arm_smmu_device *qcom_smmu_impl_init(struct arm_smmu_device *smmu);
533541
void arm_smmu_write_context_bank(struct arm_smmu_device *smmu, int idx);
534542
int arm_mmu500_reset(struct arm_smmu_device *smmu);
535543

544+
struct arm_smmu_context_fault_info {
545+
unsigned long iova;
546+
u32 fsr;
547+
u32 fsynr;
548+
u32 cbfrsynra;
549+
};
550+
551+
void arm_smmu_read_context_fault_info(struct arm_smmu_device *smmu, int idx,
552+
struct arm_smmu_context_fault_info *cfi);
553+
554+
void arm_smmu_print_context_fault_info(struct arm_smmu_device *smmu, int idx,
555+
const struct arm_smmu_context_fault_info *cfi);
556+
536557
#endif /* _ARM_SMMU_H */

0 commit comments

Comments
 (0)