[COMMON] iommu/exynos: add dump of TLB status
authorJanghyuck Kim <janghyuck.kim@samsung.com>
Thu, 16 Jun 2016 08:12:46 +0000 (17:12 +0900)
committerCosmin Tanislav <demonsingur@gmail.com>
Mon, 22 Apr 2024 17:21:52 +0000 (20:21 +0300)
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 <janghyuck.kim@samsung.com>
drivers/iommu/exynos-iommu.c
drivers/iommu/exynos-iommu.h

index 49f83cb9ec110de8c3ca34eb66c176cbcb64daea..9c55c160fa5ae32a244af51e43e73717b2735a7f 100644 (file)
@@ -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,
index 36d11eae3d74e1c26eacfba036a5c20b9a93aba3..3eb267ac85ddd57373d4d3018e7868ce7a156ead 100644 (file)
@@ -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