Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

coresight: etm4x: Modify core-commit to avoid HiSilicon ETM overflow

The ETM device can't keep up with the core pipeline when cpu core
is at full speed. This may cause overflow within core and its ETM.
This is a common phenomenon on ETM devices.

On HiSilicon Hip08 platform, a specific feature is added to set
core pipeline. So commit rate can be reduced manually to avoid ETM
overflow.

Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Signed-off-by: Qi Liu <liuqi115@huawei.com>
[Modified changelog title and Kconfig description]
Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
Link: https://lore.kernel.org/r/20201208182651.1597945-4-mathieu.poirier@linaro.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Qi Liu and committed by
Greg Kroah-Hartman
e7255092 45fe7bef

+114
+8
drivers/hwtracing/coresight/Kconfig
··· 110 110 To compile this driver as a module, choose M here: the 111 111 module will be called coresight-etm4x. 112 112 113 + config ETM4X_IMPDEF_FEATURE 114 + bool "Control implementation defined overflow support in ETM 4.x driver" 115 + depends on CORESIGHT_SOURCE_ETM4X 116 + help 117 + This control provides implementation define control for CoreSight 118 + ETM 4.x tracer module that can't reduce commit rate automatically. 119 + This avoids overflow between the ETM tracer module and the cpu core. 120 + 113 121 config CORESIGHT_STM 114 122 tristate "CoreSight System Trace Macrocell driver" 115 123 depends on (ARM && !(CPU_32v3 || CPU_32v4 || CPU_32v4T)) || ARM64
+98
drivers/hwtracing/coresight/coresight-etm4x-core.c
··· 3 3 * Copyright (c) 2014, The Linux Foundation. All rights reserved. 4 4 */ 5 5 6 + #include <linux/bitops.h> 6 7 #include <linux/kernel.h> 7 8 #include <linux/moduleparam.h> 8 9 #include <linux/init.h> ··· 29 28 #include <linux/perf_event.h> 30 29 #include <linux/pm_runtime.h> 31 30 #include <linux/property.h> 31 + 32 32 #include <asm/sections.h> 33 + #include <asm/sysreg.h> 33 34 #include <asm/local.h> 34 35 #include <asm/virt.h> 35 36 ··· 106 103 int rc; 107 104 }; 108 105 106 + #ifdef CONFIG_ETM4X_IMPDEF_FEATURE 107 + 108 + #define HISI_HIP08_AMBA_ID 0x000b6d01 109 + #define ETM4_AMBA_MASK 0xfffff 110 + #define HISI_HIP08_CORE_COMMIT_MASK 0x3000 111 + #define HISI_HIP08_CORE_COMMIT_SHIFT 12 112 + #define HISI_HIP08_CORE_COMMIT_FULL 0b00 113 + #define HISI_HIP08_CORE_COMMIT_LVL_1 0b01 114 + #define HISI_HIP08_CORE_COMMIT_REG sys_reg(3, 1, 15, 2, 5) 115 + 116 + struct etm4_arch_features { 117 + void (*arch_callback)(bool enable); 118 + }; 119 + 120 + static bool etm4_hisi_match_pid(unsigned int id) 121 + { 122 + return (id & ETM4_AMBA_MASK) == HISI_HIP08_AMBA_ID; 123 + } 124 + 125 + static void etm4_hisi_config_core_commit(bool enable) 126 + { 127 + u8 commit = enable ? HISI_HIP08_CORE_COMMIT_LVL_1 : 128 + HISI_HIP08_CORE_COMMIT_FULL; 129 + u64 val; 130 + 131 + /* 132 + * bit 12 and 13 of HISI_HIP08_CORE_COMMIT_REG are used together 133 + * to set core-commit, 2'b00 means cpu is at full speed, 2'b01, 134 + * 2'b10, 2'b11 mean reduce pipeline speed, and 2'b01 means level-1 135 + * speed(minimun value). So bit 12 and 13 should be cleared together. 136 + */ 137 + val = read_sysreg_s(HISI_HIP08_CORE_COMMIT_REG); 138 + val &= ~HISI_HIP08_CORE_COMMIT_MASK; 139 + val |= commit << HISI_HIP08_CORE_COMMIT_SHIFT; 140 + write_sysreg_s(val, HISI_HIP08_CORE_COMMIT_REG); 141 + } 142 + 143 + static struct etm4_arch_features etm4_features[] = { 144 + [ETM4_IMPDEF_HISI_CORE_COMMIT] = { 145 + .arch_callback = etm4_hisi_config_core_commit, 146 + }, 147 + {}, 148 + }; 149 + 150 + static void etm4_enable_arch_specific(struct etmv4_drvdata *drvdata) 151 + { 152 + struct etm4_arch_features *ftr; 153 + int bit; 154 + 155 + for_each_set_bit(bit, drvdata->arch_features, ETM4_IMPDEF_FEATURE_MAX) { 156 + ftr = &etm4_features[bit]; 157 + 158 + if (ftr->arch_callback) 159 + ftr->arch_callback(true); 160 + } 161 + } 162 + 163 + static void etm4_disable_arch_specific(struct etmv4_drvdata *drvdata) 164 + { 165 + struct etm4_arch_features *ftr; 166 + int bit; 167 + 168 + for_each_set_bit(bit, drvdata->arch_features, ETM4_IMPDEF_FEATURE_MAX) { 169 + ftr = &etm4_features[bit]; 170 + 171 + if (ftr->arch_callback) 172 + ftr->arch_callback(false); 173 + } 174 + } 175 + 176 + static void etm4_check_arch_features(struct etmv4_drvdata *drvdata, 177 + unsigned int id) 178 + { 179 + if (etm4_hisi_match_pid(id)) 180 + set_bit(ETM4_IMPDEF_HISI_CORE_COMMIT, drvdata->arch_features); 181 + } 182 + #else 183 + static void etm4_enable_arch_specific(struct etmv4_drvdata *drvdata) 184 + { 185 + } 186 + 187 + static void etm4_disable_arch_specific(struct etmv4_drvdata *drvdata) 188 + { 189 + } 190 + 191 + static void etm4_check_arch_features(struct etmv4_drvdata *drvdata, 192 + unsigned int id) 193 + { 194 + } 195 + #endif /* CONFIG_ETM4X_IMPDEF_FEATURE */ 196 + 109 197 static int etm4_enable_hw(struct etmv4_drvdata *drvdata) 110 198 { 111 199 int i, rc; ··· 204 110 struct device *etm_dev = &drvdata->csdev->dev; 205 111 206 112 CS_UNLOCK(drvdata->base); 113 + etm4_enable_arch_specific(drvdata); 207 114 208 115 etm4_os_unlock(drvdata); 209 116 ··· 574 479 int i; 575 480 576 481 CS_UNLOCK(drvdata->base); 482 + etm4_disable_arch_specific(drvdata); 577 483 578 484 if (!drvdata->skip_power_up) { 579 485 /* power can be removed from the trace unit now */ ··· 1658 1562 coresight_enable(drvdata->csdev); 1659 1563 drvdata->boot_enable = true; 1660 1564 } 1565 + 1566 + etm4_check_arch_features(drvdata, id->id); 1661 1567 1662 1568 return 0; 1663 1569 }
+8
drivers/hwtracing/coresight/coresight-etm4x.h
··· 8 8 9 9 #include <asm/local.h> 10 10 #include <linux/spinlock.h> 11 + #include <linux/types.h> 11 12 #include "coresight-priv.h" 12 13 13 14 /* ··· 203 202 204 203 /* Interpretation of resource numbers change at ETM v4.3 architecture */ 205 204 #define ETM4X_ARCH_4V3 0x43 205 + 206 + enum etm_impdef_type { 207 + ETM4_IMPDEF_HISI_CORE_COMMIT, 208 + ETM4_IMPDEF_FEATURE_MAX, 209 + }; 206 210 207 211 /** 208 212 * struct etmv4_config - configuration information related to an ETMv4 ··· 421 415 * @state_needs_restore: True when there is context to restore after PM exit 422 416 * @skip_power_up: Indicates if an implementation can skip powering up 423 417 * the trace unit. 418 + * @arch_features: Bitmap of arch features of etmv4 devices. 424 419 */ 425 420 struct etmv4_drvdata { 426 421 void __iomem *base; ··· 470 463 struct etmv4_save_state *save_state; 471 464 bool state_needs_restore; 472 465 bool skip_power_up; 466 + DECLARE_BITMAP(arch_features, ETM4_IMPDEF_FEATURE_MAX); 473 467 }; 474 468 475 469 /* Address comparator access types */