From 33a322a3ff9c6a6dec85362d01e0503e489ac838 Mon Sep 17 00:00:00 2001 From: Janghyuck Kim Date: Thu, 16 Jun 2016 17:12:46 +0900 Subject: [PATCH] [COMMON] iommu/exynos: add dump of TLB status Dumping TLB status and TLB set/way information are added to provide useful information in sysmmu status dumping Change-Id: I37bfdfbd1baa2c6f10275c93f3d43b055ad0b6e7 Signed-off-by: Janghyuck Kim --- drivers/iommu/exynos-iommu.c | 59 ++++++++++++++++++++++++++++++++++-- drivers/iommu/exynos-iommu.h | 15 ++++++++- 2 files changed, 71 insertions(+), 3 deletions(-) diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index 49f83cb9ec11..9c55c160fa5a 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c @@ -170,6 +170,60 @@ void exynos_sysmmu_tlb_invalidate(struct iommu_domain *iommu_domain, spin_unlock_irqrestore(&domain->lock, flags); } + +static unsigned int dump_set_associative_tlb(void __iomem *sfrbase, + int idx_way, int idx_set) +{ + if (MMU_TLB_ENTRY_VALID(__raw_readl(sfrbase + REG_TLB_ATTR))) { + pr_crit("[%02d][%02d] VPN: %#010x, PPN: %#010x, ATTR: %#010x\n", + idx_way, idx_set, + __raw_readl(sfrbase + REG_TLB_VPN), + __raw_readl(sfrbase + REG_TLB_PPN), + __raw_readl(sfrbase + REG_TLB_ATTR)); + return 1; + } + return 0; +} + +#define MMU_NUM_TLB_SUBLINE 4 +static void dump_sysmmu_tlb(void __iomem *sfrbase) +{ + int i, j, k; + u32 capa = __raw_readl(sfrbase + REG_MMU_CAPA_V7); + unsigned int cnt; + + pr_crit("TLB has %d way, %d set. SBB has %d entries.\n", + MMU_CAPA_NUM_TLB_WAY(capa), + (1 << MMU_CAPA_NUM_TLB_SET(capa)), + (1 << MMU_CAPA_NUM_SBB_ENTRY(capa))); + pr_crit("------------- TLB[WAY][SET][ENTRY] -------------\n"); + for (i = 0, cnt = 0; i < MMU_CAPA_NUM_TLB_WAY(capa); i++) { + for (j = 0; j < (1 << MMU_CAPA_NUM_TLB_SET(capa)); j++) { + for (k = 0; k < MMU_NUM_TLB_SUBLINE; k++) { + __raw_writel(MMU_SET_TLB_READ_ENTRY(j, i, k), + sfrbase + REG_TLB_READ); + cnt += dump_set_associative_tlb(sfrbase, i, j); + } + } + } + if (!cnt) + pr_crit(">> No Valid TLB Entries\n"); + + pr_crit("--- SBB(Second-Level Page Table Base Address Buffer ---\n"); + for (i = 0, cnt = 0; i < (1 << MMU_CAPA_NUM_SBB_ENTRY(capa)); i++) { + __raw_writel(i, sfrbase + REG_SBB_READ); + if (MMU_SBB_ENTRY_VALID(__raw_readl(sfrbase + REG_SBB_VPN))) { + pr_crit("[%02d] VPN: %#010x, PPN: %#010x, ATTR: %#010x\n", + i, __raw_readl(sfrbase + REG_SBB_VPN), + __raw_readl(sfrbase + REG_SBB_LINK), + __raw_readl(sfrbase + REG_SBB_ATTR)); + cnt++; + } + } + if (!cnt) + pr_crit(">> No Valid SBB Entries\n"); +} + static char *sysmmu_fault_name[SYSMMU_FAULTS_NUM] = { "PTW ACCESS FAULT", "PAGE FAULT", @@ -181,7 +235,7 @@ static char *sysmmu_fault_name[SYSMMU_FAULTS_NUM] = { void dump_sysmmu_status(void __iomem *sfrbase) { - int capa, info; + int info; pgd_t *pgd; pud_t *pud; pmd_t *pmd; @@ -212,7 +266,6 @@ void dump_sysmmu_status(void __iomem *sfrbase) return; } - capa = __raw_readl(sfrbase + REG_MMU_CAPA); info = MMU_RAW_VER(__raw_readl(sfrbase + REG_MMU_VERSION)); phys = pte_pfn(*pte) << PAGE_SHIFT; @@ -224,6 +277,8 @@ void dump_sysmmu_status(void __iomem *sfrbase) MMU_MAJ_VER(info), MMU_MIN_VER(info), MMU_REV_VER(info), __raw_readl(sfrbase + REG_MMU_CFG), __raw_readl(sfrbase + REG_MMU_STATUS)); + + dump_sysmmu_tlb(sfrbase); } static void show_fault_information(struct sysmmu_drvdata *drvdata, diff --git a/drivers/iommu/exynos-iommu.h b/drivers/iommu/exynos-iommu.h index 36d11eae3d74..3eb267ac85dd 100644 --- a/drivers/iommu/exynos-iommu.h +++ b/drivers/iommu/exynos-iommu.h @@ -134,9 +134,22 @@ typedef u32 sysmmu_pte_t; #define REG_PRIVATE_ID(n) (0x20C + ((n) * 0x10)) #define REG_FAULT_ADDR 0x070 #define REG_FAULT_TRANS_INFO 0x078 - +#define REG_TLB_READ 0x1000 +#define REG_TLB_VPN 0x1004 +#define REG_TLB_PPN 0x1008 +#define REG_TLB_ATTR 0x100C +#define REG_SBB_READ 0x1100 +#define REG_SBB_VPN 0x1104 +#define REG_SBB_LINK 0x1108 +#define REG_SBB_ATTR 0x110C + +#define MMU_CAPA_NUM_SBB_ENTRY(reg) ((reg >> 12) & 0xF) #define MMU_CAPA_NUM_TLB_SET(reg) ((reg >> 8) & 0xF) #define MMU_CAPA_NUM_TLB_WAY(reg) ((reg) & 0xFF) +#define MMU_SET_TLB_READ_ENTRY(set, way, line) \ + ((set) | ((way) << 8) | ((line) << 16)) +#define MMU_TLB_ENTRY_VALID(reg) ((reg) >> 28) +#define MMU_SBB_ENTRY_VALID(reg) ((reg) >> 28) #define MMU_FAULT_INFO_READ_REQUEST 0 #define MMU_FAULT_INFO_WRITE_REQUEST 1 -- 2.20.1