coresight-etm4x: Controls pertaining to the ViewInst register
authorPratik Patel <pratikp@codeaurora.org>
Wed, 13 May 2015 16:34:13 +0000 (10:34 -0600)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 24 May 2015 18:11:20 +0000 (11:11 -0700)
Adding sysfs entries to control the ViewInst register's event
selector along with secure and non-secure exception level
instruction tracing.

Signed-off-by: Pratik Patel <pratikp@codeaurora.org>
Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Documentation/ABI/testing/sysfs-bus-coresight-devices-etm4x
drivers/hwtracing/coresight/coresight-etm4x.c

index 7e5f9bf1d5084611b17d2f175d5f694f6a35ec74..ca0a51838e355a670de76fad475bc88b887b475b 100644 (file)
@@ -134,3 +134,23 @@ KernelVersion:     4.01
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
 Description:   (RW) Controls which regions in the memory map are enabled to
                use branch broadcasting.
+
+What:          /sys/bus/coresight/devices/<memory_map>.etm/event_vinst
+Date:          April 2015
+KernelVersion: 4.01
+Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
+Description:   (RW) Controls instruction trace filtering.
+
+What:          /sys/bus/coresight/devices/<memory_map>.etm/s_exlevel_vinst
+Date:          April 2015
+KernelVersion: 4.01
+Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
+Description:   (RW) In Secure state, each bit controls whether instruction
+               tracing is enabled for the corresponding exception level.
+
+What:          /sys/bus/coresight/devices/<memory_map>.etm/ns_exlevel_vinst
+Date:          April 2015
+KernelVersion: 4.01
+Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
+Description:   (RW) In non-secure state, each bit controls whether instruction
+               tracing is enabled for the corresponding exception level.
index 51fbda83702668d5fea8e121fea148f01752a4b3..e44cc846413427f3b7deb1354b85ce9470dbb37f 100644 (file)
@@ -932,6 +932,101 @@ static ssize_t bb_ctrl_store(struct device *dev,
 }
 static DEVICE_ATTR_RW(bb_ctrl);
 
+static ssize_t event_vinst_show(struct device *dev,
+                               struct device_attribute *attr,
+                               char *buf)
+{
+       unsigned long val;
+       struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       val = drvdata->vinst_ctrl & ETMv4_EVENT_MASK;
+       return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t event_vinst_store(struct device *dev,
+                                struct device_attribute *attr,
+                                const char *buf, size_t size)
+{
+       unsigned long val;
+       struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       if (kstrtoul(buf, 16, &val))
+               return -EINVAL;
+
+       spin_lock(&drvdata->spinlock);
+       val &= ETMv4_EVENT_MASK;
+       drvdata->vinst_ctrl &= ~ETMv4_EVENT_MASK;
+       drvdata->vinst_ctrl |= val;
+       spin_unlock(&drvdata->spinlock);
+       return size;
+}
+static DEVICE_ATTR_RW(event_vinst);
+
+static ssize_t s_exlevel_vinst_show(struct device *dev,
+                                   struct device_attribute *attr,
+                                   char *buf)
+{
+       unsigned long val;
+       struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       val = BMVAL(drvdata->vinst_ctrl, 16, 19);
+       return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t s_exlevel_vinst_store(struct device *dev,
+                                    struct device_attribute *attr,
+                                    const char *buf, size_t size)
+{
+       unsigned long val;
+       struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       if (kstrtoul(buf, 16, &val))
+               return -EINVAL;
+
+       spin_lock(&drvdata->spinlock);
+       /* clear all EXLEVEL_S bits (bit[18] is never implemented) */
+       drvdata->vinst_ctrl &= ~(BIT(16) | BIT(17) | BIT(19));
+       /* enable instruction tracing for corresponding exception level */
+       val &= drvdata->s_ex_level;
+       drvdata->vinst_ctrl |= (val << 16);
+       spin_unlock(&drvdata->spinlock);
+       return size;
+}
+static DEVICE_ATTR_RW(s_exlevel_vinst);
+
+static ssize_t ns_exlevel_vinst_show(struct device *dev,
+                                    struct device_attribute *attr,
+                                    char *buf)
+{
+       unsigned long val;
+       struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       /* EXLEVEL_NS, bits[23:20] */
+       val = BMVAL(drvdata->vinst_ctrl, 20, 23);
+       return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t ns_exlevel_vinst_store(struct device *dev,
+                                     struct device_attribute *attr,
+                                     const char *buf, size_t size)
+{
+       unsigned long val;
+       struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       if (kstrtoul(buf, 16, &val))
+               return -EINVAL;
+
+       spin_lock(&drvdata->spinlock);
+       /* clear EXLEVEL_NS bits (bit[23] is never implemented */
+       drvdata->vinst_ctrl &= ~(BIT(20) | BIT(21) | BIT(22));
+       /* enable instruction tracing for corresponding exception level */
+       val &= drvdata->ns_ex_level;
+       drvdata->vinst_ctrl |= (val << 20);
+       spin_unlock(&drvdata->spinlock);
+       return size;
+}
+static DEVICE_ATTR_RW(ns_exlevel_vinst);
+
 static ssize_t cpu_show(struct device *dev,
                        struct device_attribute *attr, char *buf)
 {
@@ -963,6 +1058,9 @@ static struct attribute *coresight_etmv4_attrs[] = {
        &dev_attr_syncfreq.attr,
        &dev_attr_cyc_threshold.attr,
        &dev_attr_bb_ctrl.attr,
+       &dev_attr_event_vinst.attr,
+       &dev_attr_s_exlevel_vinst.attr,
+       &dev_attr_ns_exlevel_vinst.attr,
        &dev_attr_cpu.attr,
        NULL,
 };