diff options
Diffstat (limited to 'drivers/hwtracing/coresight/coresight-trbe.c')
| -rw-r--r-- | drivers/hwtracing/coresight/coresight-trbe.c | 60 |
1 files changed, 38 insertions, 22 deletions
diff --git a/drivers/hwtracing/coresight/coresight-trbe.c b/drivers/hwtracing/coresight/coresight-trbe.c index 96a32b213669..474861903f6c 100644 --- a/drivers/hwtracing/coresight/coresight-trbe.c +++ b/drivers/hwtracing/coresight/coresight-trbe.c @@ -17,12 +17,14 @@ #include <asm/barrier.h> #include <asm/cpufeature.h> +#include <linux/kvm_host.h> #include <linux/vmalloc.h> #include "coresight-self-hosted-trace.h" #include "coresight-trbe.h" -#define PERF_IDX2OFF(idx, buf) ((idx) % ((buf)->nr_pages << PAGE_SHIFT)) +#define PERF_IDX2OFF(idx, buf) \ + ((idx) % ((unsigned long)(buf)->nr_pages << PAGE_SHIFT)) /* * A padding packet that will help the user space tools @@ -159,22 +161,22 @@ static void trbe_check_errata(struct trbe_cpudata *cpudata) } } -static inline bool trbe_has_erratum(struct trbe_cpudata *cpudata, int i) +static bool trbe_has_erratum(struct trbe_cpudata *cpudata, int i) { return (i < TRBE_ERRATA_MAX) && test_bit(i, cpudata->errata); } -static inline bool trbe_may_overwrite_in_fill_mode(struct trbe_cpudata *cpudata) +static bool trbe_may_overwrite_in_fill_mode(struct trbe_cpudata *cpudata) { return trbe_has_erratum(cpudata, TRBE_WORKAROUND_OVERWRITE_FILL_MODE); } -static inline bool trbe_may_write_out_of_range(struct trbe_cpudata *cpudata) +static bool trbe_may_write_out_of_range(struct trbe_cpudata *cpudata) { return trbe_has_erratum(cpudata, TRBE_WORKAROUND_WRITE_OUT_OF_RANGE); } -static inline bool trbe_needs_drain_after_disable(struct trbe_cpudata *cpudata) +static bool trbe_needs_drain_after_disable(struct trbe_cpudata *cpudata) { /* * Errata affected TRBE implementation will need TSB CSYNC and @@ -184,7 +186,7 @@ static inline bool trbe_needs_drain_after_disable(struct trbe_cpudata *cpudata) return trbe_has_erratum(cpudata, TRBE_NEEDS_DRAIN_AFTER_DISABLE); } -static inline bool trbe_needs_ctxt_sync_after_enable(struct trbe_cpudata *cpudata) +static bool trbe_needs_ctxt_sync_after_enable(struct trbe_cpudata *cpudata) { /* * Errata affected TRBE implementation will need an additional @@ -195,7 +197,7 @@ static inline bool trbe_needs_ctxt_sync_after_enable(struct trbe_cpudata *cpudat return trbe_has_erratum(cpudata, TRBE_NEEDS_CTXT_SYNC_AFTER_ENABLE); } -static inline bool trbe_is_broken(struct trbe_cpudata *cpudata) +static bool trbe_is_broken(struct trbe_cpudata *cpudata) { return trbe_has_erratum(cpudata, TRBE_IS_BROKEN); } @@ -207,13 +209,13 @@ static int trbe_alloc_node(struct perf_event *event) return cpu_to_node(event->cpu); } -static inline void trbe_drain_buffer(void) +static void trbe_drain_buffer(void) { tsb_csync(); dsb(nsh); } -static inline void set_trbe_enabled(struct trbe_cpudata *cpudata, u64 trblimitr) +static void set_trbe_enabled(struct trbe_cpudata *cpudata, u64 trblimitr) { /* * Enable the TRBE without clearing LIMITPTR which @@ -221,6 +223,7 @@ static inline void set_trbe_enabled(struct trbe_cpudata *cpudata, u64 trblimitr) */ trblimitr |= TRBLIMITR_EL1_E; write_sysreg_s(trblimitr, SYS_TRBLIMITR_EL1); + kvm_enable_trbe(); /* Synchronize the TRBE enable event */ isb(); @@ -229,7 +232,7 @@ static inline void set_trbe_enabled(struct trbe_cpudata *cpudata, u64 trblimitr) isb(); } -static inline void set_trbe_disabled(struct trbe_cpudata *cpudata) +static void set_trbe_disabled(struct trbe_cpudata *cpudata) { u64 trblimitr = read_sysreg_s(SYS_TRBLIMITR_EL1); @@ -239,6 +242,7 @@ static inline void set_trbe_disabled(struct trbe_cpudata *cpudata) */ trblimitr &= ~TRBLIMITR_EL1_E; write_sysreg_s(trblimitr, SYS_TRBLIMITR_EL1); + kvm_disable_trbe(); if (trbe_needs_drain_after_disable(cpudata)) trbe_drain_buffer(); @@ -253,8 +257,9 @@ static void trbe_drain_and_disable_local(struct trbe_cpudata *cpudata) static void trbe_reset_local(struct trbe_cpudata *cpudata) { - trbe_drain_and_disable_local(cpudata); write_sysreg_s(0, SYS_TRBLIMITR_EL1); + isb(); + trbe_drain_buffer(); write_sysreg_s(0, SYS_TRBPTR_EL1); write_sysreg_s(0, SYS_TRBBASER_EL1); write_sysreg_s(0, SYS_TRBSR_EL1); @@ -744,12 +749,12 @@ static void *arm_trbe_alloc_buffer(struct coresight_device *csdev, buf = kzalloc_node(sizeof(*buf), GFP_KERNEL, trbe_alloc_node(event)); if (!buf) - return ERR_PTR(-ENOMEM); + return NULL; pglist = kcalloc(nr_pages, sizeof(*pglist), GFP_KERNEL); if (!pglist) { kfree(buf); - return ERR_PTR(-ENOMEM); + return NULL; } for (i = 0; i < nr_pages; i++) @@ -759,7 +764,7 @@ static void *arm_trbe_alloc_buffer(struct coresight_device *csdev, if (!buf->trbe_base) { kfree(pglist); kfree(buf); - return ERR_PTR(-ENOMEM); + return NULL; } buf->trbe_limit = buf->trbe_base + nr_pages * PAGE_SIZE; buf->trbe_write = buf->trbe_base; @@ -1008,11 +1013,11 @@ err: } static int arm_trbe_enable(struct coresight_device *csdev, enum cs_mode mode, - void *data) + struct coresight_path *path) { struct trbe_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); struct trbe_cpudata *cpudata = dev_get_drvdata(&csdev->dev); - struct perf_output_handle *handle = data; + struct perf_output_handle *handle = path->handle; struct trbe_buf *buf = etm_perf_sink_config(handle); WARN_ON(cpudata->cpu != smp_processor_id()); @@ -1110,6 +1115,16 @@ static bool is_perf_trbe(struct perf_output_handle *handle) return true; } +static u64 cpu_prohibit_trace(void) +{ + u64 trfcr = read_trfcr(); + + /* Prohibit tracing at EL0 & the kernel EL */ + write_trfcr(trfcr & ~(TRFCR_EL1_ExTRE | TRFCR_EL1_E0TRE)); + /* Return the original value of the TRFCR */ + return trfcr; +} + static irqreturn_t arm_trbe_irq_handler(int irq, void *dev) { struct perf_output_handle **handle_ptr = dev; @@ -1266,7 +1281,7 @@ static void arm_trbe_register_coresight_cpu(struct trbe_drvdata *drvdata, int cp * into the device for that purpose. */ desc.pdata = devm_kzalloc(dev, sizeof(*desc.pdata), GFP_KERNEL); - if (IS_ERR(desc.pdata)) + if (!desc.pdata) goto cpu_clear; desc.type = CORESIGHT_DEV_TYPE_SINK; @@ -1459,9 +1474,10 @@ static void arm_trbe_remove_cpuhp(struct trbe_drvdata *drvdata) static int arm_trbe_probe_irq(struct platform_device *pdev, struct trbe_drvdata *drvdata) { + const struct cpumask *affinity; int ret; - drvdata->irq = platform_get_irq(pdev, 0); + drvdata->irq = platform_get_irq_affinity(pdev, 0, &affinity); if (drvdata->irq < 0) { pr_err("IRQ not found for the platform device\n"); return drvdata->irq; @@ -1472,14 +1488,14 @@ static int arm_trbe_probe_irq(struct platform_device *pdev, return -EINVAL; } - if (irq_get_percpu_devid_partition(drvdata->irq, &drvdata->supported_cpus)) - return -EINVAL; + cpumask_copy(&drvdata->supported_cpus, affinity); drvdata->handle = alloc_percpu(struct perf_output_handle *); if (!drvdata->handle) return -ENOMEM; - ret = request_percpu_irq(drvdata->irq, arm_trbe_irq_handler, DRVNAME, drvdata->handle); + ret = request_percpu_irq_affinity(drvdata->irq, arm_trbe_irq_handler, DRVNAME, + affinity, drvdata->handle); if (ret) { free_percpu(drvdata->handle); return ret; @@ -1562,7 +1578,7 @@ static struct platform_driver arm_trbe_driver = { .suppress_bind_attrs = true, }, .probe = arm_trbe_device_probe, - .remove_new = arm_trbe_device_remove, + .remove = arm_trbe_device_remove, }; static int __init arm_trbe_init(void) |
