* [PATCH v4 1/2] perf: riscv: preliminary RISC-V support
From: Alan Kao @ 2018-04-18 2:12 UTC (permalink / raw)
To: Palmer Dabbelt, Albert Ou, Peter Zijlstra, Ingo Molnar,
Arnaldo Carvalho de Melo, Alexander Shishkin, Jiri Olsa,
Namhyung Kim, Alex Solomatnikov, Jonathan Corbet, linux-riscv,
linux-doc, linux-kernel
Cc: Alan Kao, Nick Hu, Greentime Hu
In-Reply-To: <1524017523-25076-1-git-send-email-alankao@andestech.com>
This patch provide a basic PMU, riscv_base_pmu, which supports two
general hardware event, instructions and cycles. Furthermore, this
PMU serves as a reference implementation to ease the portings in
the future.
riscv_base_pmu should be able to run on any RISC-V machine that
conforms to the Priv-Spec. Note that the latest qemu model hasn't
fully support a proper behavior of Priv-Spec 1.10 yet, but work
around should be easy with very small fixes. Please check
https://github.com/riscv/riscv-qemu/pull/115 for future updates.
Cc: Nick Hu <nickhu@andestech.com>
Cc: Greentime Hu <greentime@andestech.com>
Signed-off-by: Alan Kao <alankao@andestech.com>
---
arch/riscv/Kconfig | 13 +
arch/riscv/include/asm/perf_event.h | 79 ++++-
arch/riscv/kernel/Makefile | 1 +
arch/riscv/kernel/perf_event.c | 482 ++++++++++++++++++++++++++++
4 files changed, 571 insertions(+), 4 deletions(-)
create mode 100644 arch/riscv/kernel/perf_event.c
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index c22ebe08e902..90d9c8e50377 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -203,6 +203,19 @@ config RISCV_ISA_C
config RISCV_ISA_A
def_bool y
+menu "supported PMU type"
+ depends on PERF_EVENTS
+
+config RISCV_BASE_PMU
+ bool "Base Performance Monitoring Unit"
+ def_bool y
+ help
+ A base PMU that serves as a reference implementation and has limited
+ feature of perf. It can run on any RISC-V machines so serves as the
+ fallback, but this option can also be disable to reduce kernel size.
+
+endmenu
+
endmenu
menu "Kernel type"
diff --git a/arch/riscv/include/asm/perf_event.h b/arch/riscv/include/asm/perf_event.h
index e13d2ff29e83..0e638a0c3feb 100644
--- a/arch/riscv/include/asm/perf_event.h
+++ b/arch/riscv/include/asm/perf_event.h
@@ -1,13 +1,84 @@
+/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2018 SiFive
+ * Copyright (C) 2018 Andes Technology Corporation
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public Licence
- * as published by the Free Software Foundation; either version
- * 2 of the Licence, or (at your option) any later version.
*/
#ifndef _ASM_RISCV_PERF_EVENT_H
#define _ASM_RISCV_PERF_EVENT_H
+#include <linux/perf_event.h>
+#include <linux/ptrace.h>
+
+#define RISCV_BASE_COUNTERS 2
+
+/*
+ * The RISCV_MAX_COUNTERS parameter should be specified.
+ */
+
+#ifdef CONFIG_RISCV_BASE_PMU
+#define RISCV_MAX_COUNTERS 2
+#endif
+
+#ifndef RISCV_MAX_COUNTERS
+#error "Please provide a valid RISCV_MAX_COUNTERS for the PMU."
+#endif
+
+/*
+ * These are the indexes of bits in counteren register *minus* 1,
+ * except for cycle. It would be coherent if it can directly mapped
+ * to counteren bit definition, but there is a *time* register at
+ * counteren[1]. Per-cpu structure is scarce resource here.
+ *
+ * According to the spec, an implementation can support counter up to
+ * mhpmcounter31, but many high-end processors has at most 6 general
+ * PMCs, we give the definition to MHPMCOUNTER8 here.
+ */
+#define RISCV_PMU_CYCLE 0
+#define RISCV_PMU_INSTRET 1
+#define RISCV_PMU_MHPMCOUNTER3 2
+#define RISCV_PMU_MHPMCOUNTER4 3
+#define RISCV_PMU_MHPMCOUNTER5 4
+#define RISCV_PMU_MHPMCOUNTER6 5
+#define RISCV_PMU_MHPMCOUNTER7 6
+#define RISCV_PMU_MHPMCOUNTER8 7
+
+#define RISCV_OP_UNSUPP (-EOPNOTSUPP)
+
+struct cpu_hw_events {
+ /* # currently enabled events*/
+ int n_events;
+ /* currently enabled events */
+ struct perf_event *events[RISCV_MAX_COUNTERS];
+ /* vendor-defined PMU data */
+ void *platform;
+};
+
+struct riscv_pmu {
+ struct pmu *pmu;
+
+ /* generic hw/cache events table */
+ const int *hw_events;
+ const int (*cache_events)[PERF_COUNT_HW_CACHE_MAX]
+ [PERF_COUNT_HW_CACHE_OP_MAX]
+ [PERF_COUNT_HW_CACHE_RESULT_MAX];
+ /* method used to map hw/cache events */
+ int (*map_hw_event)(u64 config);
+ int (*map_cache_event)(u64 config);
+
+ /* max generic hw events in map */
+ int max_events;
+ /* number total counters, 2(base) + x(general) */
+ int num_counters;
+ /* the width of the counter */
+ int counter_width;
+
+ /* vendor-defined PMU features */
+ void *platform;
+
+ irqreturn_t (*handle_irq)(int irq_num, void *dev);
+ int irq;
+};
+
#endif /* _ASM_RISCV_PERF_EVENT_H */
diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
index ffa439d4a364..f50d19816757 100644
--- a/arch/riscv/kernel/Makefile
+++ b/arch/riscv/kernel/Makefile
@@ -39,5 +39,6 @@ obj-$(CONFIG_MODULE_SECTIONS) += module-sections.o
obj-$(CONFIG_FUNCTION_TRACER) += mcount.o
obj-$(CONFIG_DYNAMIC_FTRACE) += mcount-dyn.o
obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
+obj-$(CONFIG_PERF_EVENTS) += perf_event.o
clean:
diff --git a/arch/riscv/kernel/perf_event.c b/arch/riscv/kernel/perf_event.c
new file mode 100644
index 000000000000..ba3192afc470
--- /dev/null
+++ b/arch/riscv/kernel/perf_event.c
@@ -0,0 +1,482 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2008 Thomas Gleixner <tglx@linutronix.de>
+ * Copyright (C) 2008-2009 Red Hat, Inc., Ingo Molnar
+ * Copyright (C) 2009 Jaswinder Singh Rajput
+ * Copyright (C) 2009 Advanced Micro Devices, Inc., Robert Richter
+ * Copyright (C) 2008-2009 Red Hat, Inc., Peter Zijlstra
+ * Copyright (C) 2009 Intel Corporation, <markus.t.metzger@intel.com>
+ * Copyright (C) 2009 Google, Inc., Stephane Eranian
+ * Copyright 2014 Tilera Corporation. All Rights Reserved.
+ * Copyright (C) 2018 Andes Technology Corporation
+ *
+ * Perf_events support for RISC-V platforms.
+ *
+ * Since the spec. (as of now, Priv-Spec 1.10) does not provide enough
+ * functionality for perf event to fully work, this file provides
+ * the very basic framework only.
+ *
+ * For platform portings, please check Documentations/riscv/pmu.txt.
+ *
+ * The Copyright line includes x86 and tile ones.
+ */
+
+#include <linux/kprobes.h>
+#include <linux/kernel.h>
+#include <linux/kdebug.h>
+#include <linux/mutex.h>
+#include <linux/bitmap.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/perf_event.h>
+#include <linux/atomic.h>
+#include <linux/of.h>
+#include <asm/perf_event.h>
+
+static const struct riscv_pmu *riscv_pmu __read_mostly;
+static DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events);
+
+/*
+ * Hardware & cache maps and their methods
+ */
+
+static const int riscv_hw_event_map[] = {
+ [PERF_COUNT_HW_CPU_CYCLES] = RISCV_PMU_CYCLE,
+ [PERF_COUNT_HW_INSTRUCTIONS] = RISCV_PMU_INSTRET,
+ [PERF_COUNT_HW_CACHE_REFERENCES] = RISCV_OP_UNSUPP,
+ [PERF_COUNT_HW_CACHE_MISSES] = RISCV_OP_UNSUPP,
+ [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = RISCV_OP_UNSUPP,
+ [PERF_COUNT_HW_BRANCH_MISSES] = RISCV_OP_UNSUPP,
+ [PERF_COUNT_HW_BUS_CYCLES] = RISCV_OP_UNSUPP,
+};
+
+#define C(x) PERF_COUNT_HW_CACHE_##x
+static const int riscv_cache_event_map[PERF_COUNT_HW_CACHE_MAX]
+[PERF_COUNT_HW_CACHE_OP_MAX]
+[PERF_COUNT_HW_CACHE_RESULT_MAX] = {
+ [C(L1D)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
+ [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
+ [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
+ [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
+ },
+ },
+ [C(L1I)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
+ [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
+ [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
+ [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
+ },
+ },
+ [C(LL)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
+ [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
+ [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
+ [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
+ },
+ },
+ [C(DTLB)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
+ [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
+ [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
+ [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
+ },
+ },
+ [C(ITLB)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
+ [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
+ [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
+ [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
+ },
+ },
+ [C(BPU)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
+ [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
+ [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
+ [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
+ },
+ },
+};
+
+static int riscv_map_hw_event(u64 config)
+{
+ if (config >= riscv_pmu->max_events)
+ return -EINVAL;
+
+ return riscv_pmu->hw_events[config];
+}
+
+int riscv_map_cache_decode(u64 config, unsigned int *type,
+ unsigned int *op, unsigned int *result)
+{
+ return -ENOENT;
+}
+
+static int riscv_map_cache_event(u64 config)
+{
+ unsigned int type, op, result;
+ int err = -ENOENT;
+ int code;
+
+ err = riscv_map_cache_decode(config, &type, &op, &result);
+ if (!riscv_pmu->cache_events || err)
+ return err;
+
+ if (type >= PERF_COUNT_HW_CACHE_MAX ||
+ op >= PERF_COUNT_HW_CACHE_OP_MAX ||
+ result >= PERF_COUNT_HW_CACHE_RESULT_MAX)
+ return -EINVAL;
+
+ code = (*riscv_pmu->cache_events)[type][op][result];
+ if (code == RISCV_OP_UNSUPP)
+ return -EINVAL;
+
+ return code;
+}
+
+/*
+ * Low-level functions: reading/writing counters
+ */
+
+static inline u64 read_counter(int idx)
+{
+ u64 val = 0;
+
+ switch (idx) {
+ case RISCV_PMU_CYCLE:
+ val = csr_read(cycle);
+ break;
+ case RISCV_PMU_INSTRET:
+ val = csr_read(instret);
+ break;
+ default:
+ WARN_ON_ONCE(idx < 0 || idx > RISCV_MAX_COUNTERS);
+ return -EINVAL;
+ }
+
+ return val;
+}
+
+static inline void write_counter(int idx, u64 value)
+{
+ /* currently not supported */
+ WARN_ON_ONCE(1);
+}
+
+/*
+ * pmu->read: read and update the counter
+ *
+ * Other architectures' implementation often have a xxx_perf_event_update
+ * routine, which can return counter values when called in the IRQ, but
+ * return void when being called by the pmu->read method.
+ */
+static void riscv_pmu_read(struct perf_event *event)
+{
+ struct hw_perf_event *hwc = &event->hw;
+ u64 prev_raw_count, new_raw_count;
+ u64 oldval;
+ int idx = hwc->idx;
+ u64 delta;
+
+ do {
+ prev_raw_count = local64_read(&hwc->prev_count);
+ new_raw_count = read_counter(idx);
+
+ oldval = local64_cmpxchg(&hwc->prev_count, prev_raw_count,
+ new_raw_count);
+ } while (oldval != prev_raw_count);
+
+ /*
+ * delta is the value to update the counter we maintain in the kernel.
+ */
+ delta = (new_raw_count - prev_raw_count) &
+ ((1ULL << riscv_pmu->counter_width) - 1);
+ local64_add(delta, &event->count);
+ /*
+ * Something like local64_sub(delta, &hwc->period_left) here is
+ * needed if there is an interrupt for perf.
+ */
+}
+
+/*
+ * State transition functions:
+ *
+ * stop()/start() & add()/del()
+ */
+
+/*
+ * pmu->stop: stop the counter
+ */
+static void riscv_pmu_stop(struct perf_event *event, int flags)
+{
+ struct hw_perf_event *hwc = &event->hw;
+
+ WARN_ON_ONCE(hwc->state & PERF_HES_STOPPED);
+ hwc->state |= PERF_HES_STOPPED;
+
+ if ((flags & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) {
+ riscv_pmu->pmu->read(event);
+ hwc->state |= PERF_HES_UPTODATE;
+ }
+}
+
+/*
+ * pmu->start: start the event.
+ */
+static void riscv_pmu_start(struct perf_event *event, int flags)
+{
+ struct hw_perf_event *hwc = &event->hw;
+
+ if (WARN_ON_ONCE(!(event->hw.state & PERF_HES_STOPPED)))
+ return;
+
+ if (flags & PERF_EF_RELOAD) {
+ WARN_ON_ONCE(!(event->hw.state & PERF_HES_UPTODATE));
+
+ /*
+ * Set the counter to the period to the next interrupt here,
+ * if you have any.
+ */
+ }
+
+ hwc->state = 0;
+ perf_event_update_userpage(event);
+
+ /*
+ * Since we cannot write to counters, this serves as an initialization
+ * to the delta-mechanism in pmu->read(); otherwise, the delta would be
+ * wrong when pmu->read is called for the first time.
+ */
+ local64_set(&hwc->prev_count, read_counter(hwc->idx));
+}
+
+/*
+ * pmu->add: add the event to PMU.
+ */
+static int riscv_pmu_add(struct perf_event *event, int flags)
+{
+ struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+ struct hw_perf_event *hwc = &event->hw;
+
+ if (cpuc->n_events == riscv_pmu->num_counters)
+ return -ENOSPC;
+
+ /*
+ * We don't have general conunters, so no binding-event-to-counter
+ * process here.
+ *
+ * Indexing using hwc->config generally not works, since config may
+ * contain extra information, but here the only info we have in
+ * hwc->config is the event index.
+ */
+ hwc->idx = hwc->config;
+ cpuc->events[hwc->idx] = event;
+ cpuc->n_events++;
+
+ hwc->state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
+
+ if (flags & PERF_EF_START)
+ riscv_pmu->pmu->start(event, PERF_EF_RELOAD);
+
+ return 0;
+}
+
+/*
+ * pmu->del: delete the event from PMU.
+ */
+static void riscv_pmu_del(struct perf_event *event, int flags)
+{
+ struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+ struct hw_perf_event *hwc = &event->hw;
+
+ cpuc->events[hwc->idx] = NULL;
+ cpuc->n_events--;
+ riscv_pmu->pmu->stop(event, PERF_EF_UPDATE);
+ perf_event_update_userpage(event);
+}
+
+/*
+ * Interrupt: a skeletion for reference.
+ */
+
+static DEFINE_MUTEX(pmc_reserve_mutex);
+
+irqreturn_t riscv_base_pmu_handle_irq(int irq_num, void *dev)
+{
+ return IRQ_NONE;
+}
+
+static int reserve_pmc_hardware(void)
+{
+ int err = 0;
+
+ mutex_lock(&pmc_reserve_mutex);
+ if (riscv_pmu->irq >=0 && riscv_pmu->handle_irq) {
+ err = request_irq(riscv_pmu->irq, riscv_pmu->handle_irq,
+ IRQF_PERCPU, "riscv-base-perf", NULL);
+ }
+ mutex_unlock(&pmc_reserve_mutex);
+
+ return err;
+}
+
+void release_pmc_hardware(void)
+{
+ mutex_lock(&pmc_reserve_mutex);
+ if (riscv_pmu->irq >=0) {
+ free_irq(riscv_pmu->irq, NULL);
+ }
+ mutex_unlock(&pmc_reserve_mutex);
+}
+
+/*
+ * Event Initialization/Finalization
+ */
+
+static atomic_t riscv_active_events = ATOMIC_INIT(0);
+
+static void riscv_event_destroy(struct perf_event *event)
+{
+ if (atomic_dec_return(&riscv_active_events) == 0)
+ release_pmc_hardware();
+}
+
+static int riscv_event_init(struct perf_event *event)
+{
+ struct perf_event_attr *attr = &event->attr;
+ struct hw_perf_event *hwc = &event->hw;
+ int err;
+ int code;
+
+ if (atomic_inc_return(&riscv_active_events) == 1) {
+ err = reserve_pmc_hardware();
+
+ if (err) {
+ pr_warn("PMC hardware not available\n");
+ atomic_dec(&riscv_active_events);
+ return -EBUSY;
+ }
+ }
+
+ switch (event->attr.type) {
+ case PERF_TYPE_HARDWARE:
+ code = riscv_pmu->map_hw_event(attr->config);
+ break;
+ case PERF_TYPE_HW_CACHE:
+ code = riscv_pmu->map_cache_event(attr->config);
+ break;
+ case PERF_TYPE_RAW:
+ return -EOPNOTSUPP;
+ default:
+ return -ENOENT;
+ }
+
+ event->destroy = riscv_event_destroy;
+ if (code < 0) {
+ event->destroy(event);
+ return code;
+ }
+
+ /*
+ * idx is set to -1 because the index of a general event should not be
+ * decided until binding to some counter in pmu->add().
+ *
+ * But since we don't have such support, later in pmu->add(), we just
+ * use hwc->config as the index instead.
+ */
+ hwc->config = code;
+ hwc->idx = -1;
+
+ return 0;
+}
+
+/*
+ * Initialization
+ */
+
+static struct pmu min_pmu = {
+ .name = "riscv-base",
+ .event_init = riscv_event_init,
+ .add = riscv_pmu_add,
+ .del = riscv_pmu_del,
+ .start = riscv_pmu_start,
+ .stop = riscv_pmu_stop,
+ .read = riscv_pmu_read,
+};
+
+static const struct riscv_pmu riscv_base_pmu = {
+ .pmu = &min_pmu,
+ .max_events = ARRAY_SIZE(riscv_hw_event_map),
+ .map_hw_event = riscv_map_hw_event,
+ .hw_events = riscv_hw_event_map,
+ .map_cache_event = riscv_map_cache_event,
+ .cache_events = &riscv_cache_event_map,
+ .counter_width = 63,
+ .num_counters = RISCV_BASE_COUNTERS + 0,
+ .handle_irq = &riscv_base_pmu_handle_irq,
+
+ /* This means this PMU has no IRQ. */
+ .irq = -1,
+};
+
+static const struct of_device_id riscv_pmu_of_ids[] = {
+ {.compatible = "riscv,base-pmu", .data = &riscv_base_pmu},
+ { /* sentinel value */ }
+};
+
+int __init init_hw_perf_events(void)
+{
+ struct device_node *node = of_find_node_by_type(NULL, "pmu");
+ const struct of_device_id *of_id;
+
+ if (node && (of_id = of_match_node(riscv_pmu_of_ids, node)))
+ riscv_pmu = of_id->data;
+ else
+ riscv_pmu = &riscv_base_pmu;
+
+ perf_pmu_register(riscv_pmu->pmu, "cpu", PERF_TYPE_RAW);
+ return 0;
+}
+arch_initcall(init_hw_perf_events);
--
2.17.0
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH v4 2/2] perf: riscv: Add Document for Future Porting Guide
From: Alan Kao @ 2018-04-18 2:12 UTC (permalink / raw)
To: Palmer Dabbelt, Albert Ou, Peter Zijlstra, Ingo Molnar,
Arnaldo Carvalho de Melo, Alexander Shishkin, Jiri Olsa,
Namhyung Kim, Alex Solomatnikov, Jonathan Corbet, linux-riscv,
linux-doc, linux-kernel
Cc: Alan Kao, Nick Hu, Greentime Hu
In-Reply-To: <1524017523-25076-1-git-send-email-alankao@andestech.com>
Reviewed-by: Alex Solomatnikov <sols@sifive.com>
Cc: Nick Hu <nickhu@andestech.com>
Cc: Greentime Hu <greentime@andestech.com>
Signed-off-by: Alan Kao <alankao@andestech.com>
---
Documentation/riscv/pmu.txt | 249 ++++++++++++++++++++++++++++++++++++
1 file changed, 249 insertions(+)
create mode 100644 Documentation/riscv/pmu.txt
diff --git a/Documentation/riscv/pmu.txt b/Documentation/riscv/pmu.txt
new file mode 100644
index 000000000000..b29f03a6d82f
--- /dev/null
+++ b/Documentation/riscv/pmu.txt
@@ -0,0 +1,249 @@
+Supporting PMUs on RISC-V platforms
+==========================================
+Alan Kao <alankao@andestech.com>, Mar 2018
+
+Introduction
+------------
+
+As of this writing, perf_event-related features mentioned in The RISC-V ISA
+Privileged Version 1.10 are as follows:
+(please check the manual for more details)
+
+* [m|s]counteren
+* mcycle[h], cycle[h]
+* minstret[h], instret[h]
+* mhpeventx, mhpcounterx[h]
+
+With such function set only, porting perf would require a lot of work, due to
+the lack of the following general architectural performance monitoring features:
+
+* Enabling/Disabling counters
+ Counters are just free-running all the time in our case.
+* Interrupt caused by counter overflow
+ No such feature in the spec.
+* Interrupt indicator
+ It is not possible to have many interrupt ports for all counters, so an
+ interrupt indicator is required for software to tell which counter has
+ just overflowed.
+* Writing to counters
+ There will be an SBI to support this since the kernel cannot modify the
+ counters [1]. Alternatively, some vendor considers to implement
+ hardware-extension for M-S-U model machines to write counters directly.
+
+This document aims to provide developers a quick guide on supporting their
+PMUs in the kernel. The following sections briefly explain perf' mechanism
+and todos.
+
+You may check previous discussions here [1][2]. Also, it might be helpful
+to check the appendix for related kernel structures.
+
+
+1. Initialization
+-----------------
+
+*riscv_pmu* is a global pointer of type *struct riscv_pmu*, which contains
+various methods according to perf's internal convention and PMU-specific
+parameters. One should declare such instance to represent the PMU. By default,
+*riscv_pmu* points to a constant structure *riscv_base_pmu*, which has very
+basic support to a baseline QEMU model.
+
+Then he/she can either assign the instance's pointer to *riscv_pmu* so that
+the minimal and already-implemented logic can be leveraged, or invent his/her
+own *riscv_init_platform_pmu* implementation.
+
+In other words, existing sources of *riscv_base_pmu* merely provide a
+reference implementation. Developers can flexibly decide how many parts they
+can leverage, and in the most extreme case, they can customize every function
+according to their needs.
+
+
+2. Event Initialization
+-----------------------
+
+When a user launches a perf command to monitor some events, it is first
+interpreted by the userspace perf tool into multiple *perf_event_open*
+system calls, and then each of them calls to the body of *event_init*
+member function that was assigned in the previous step. In *riscv_base_pmu*'s
+case, it is *riscv_event_init*.
+
+The main purpose of this function is to translate the event provided by user
+into bitmap, so that HW-related control registers or counters can directly be
+manipulated. The translation is based on the mappings and methods provided in
+*riscv_pmu*.
+
+Note that some features can be done in this stage as well:
+
+(1) interrupt setting, which is stated in the next section;
+(2) privilege level setting (user space only, kernel space only, both);
+(3) destructor setting. Normally it is sufficient to apply *riscv_destroy_event*;
+(4) tweaks for non-sampling events, which will be utilized by functions such as
+*perf_adjust_period*, usually something like the follows:
+
+if (!is_sampling_event(event)) {
+ hwc->sample_period = x86_pmu.max_period;
+ hwc->last_period = hwc->sample_period;
+ local64_set(&hwc->period_left, hwc->sample_period);
+}
+
+In the case of *riscv_base_pmu*, only (3) is provided for now.
+
+
+3. Interrupt
+------------
+
+3.1. Interrupt Initialization
+
+This often occurs at the beginning of the *event_init* method. In common
+practice, this should be a code segment like
+
+int x86_reserve_hardware(void)
+{
+ int err = 0;
+
+ if (!atomic_inc_not_zero(&pmc_refcount)) {
+ mutex_lock(&pmc_reserve_mutex);
+ if (atomic_read(&pmc_refcount) == 0) {
+ if (!reserve_pmc_hardware())
+ err = -EBUSY;
+ else
+ reserve_ds_buffers();
+ }
+ if (!err)
+ atomic_inc(&pmc_refcount);
+ mutex_unlock(&pmc_reserve_mutex);
+ }
+
+ return err;
+}
+
+And the magic is in *reserve_pmc_hardware*, which usually does atomic
+operations to make implemented IRQ accessible from some global function pointer.
+*release_pmc_hardware* serves the opposite purpose, and it is used in event
+destructors mentioned in previous section.
+
+(Note: From the implementations in all the architectures, the *reserve/release*
+pair are always IRQ settings, so the *pmc_hardware* seems somehow misleading.
+It does NOT deal with the binding between an event and a physical counter,
+which will be introduced in the next section.)
+
+3.2. IRQ Structure
+
+Basically, a IRQ runs the following pseudo code:
+
+for each hardware counter that triggered this overflow
+
+ get the event of this counter
+
+ // following two steps are defined as *read()*,
+ // check the section Reading/Writing Counters for details.
+ count the delta value since previous interrupt
+ update the event->count (# event occurs) by adding delta, and
+ event->hw.period_left by subtracting delta
+
+ if the event overflows
+ sample data
+ set the counter appropriately for the next overflow
+
+ if the event overflows again
+ too frequently, throttle this event
+ fi
+ fi
+
+end for
+
+However as of this writing, none of the RISC-V implementations have designed an
+interrupt for perf, so the details are to be completed in the future.
+
+4. Reading/Writing Counters
+---------------------------
+
+They seem symmetric but perf treats them quite differently. For reading, there
+is a *read* interface in *struct pmu*, but it serves more than just reading.
+According to the context, the *read* function not only reads the content of the
+counter (event->count), but also updates the left period to the next interrupt
+(event->hw.period_left).
+
+But the core of perf does not need direct write to counters. Writing counters
+is hidden behind the abstraction of 1) *pmu->start*, literally start counting so one
+has to set the counter to a good value for the next interrupt; 2) inside the IRQ
+it should set the counter to the same resonable value.
+
+Reading is not a problem in RISC-V but writing would need some effort, since
+counters are not allowed to be written by S-mode.
+
+
+5. add()/del()/start()/stop()
+-----------------------------
+
+Basic idea: add()/del() adds/deletes events to/from a PMU, and start()/stop()
+starts/stop the counter of some event in the PMU. All of them take the same
+arguments: *struct perf_event *event* and *int flag*.
+
+Consider perf as a state machine, then you will find that these functions serve
+as the state transition process between those states.
+Three states (event->hw.state) are defined:
+
+* PERF_HES_STOPPED: the counter is stopped
+* PERF_HES_UPTODATE: the event->count is up-to-date
+* PERF_HES_ARCH: arch-dependent usage ... we don't need this for now
+
+A normal flow of these state transitions are as follows:
+
+* A user launches a perf event, resulting in calling to *event_init*.
+* When being context-switched in, *add* is called by the perf core, with a flag
+ PERF_EF_START, which means that the event should be started after it is added.
+ At this stage, a general event is bound to a physical counter, if any.
+ The state changes to PERF_HES_STOPPED and PERF_HES_UPTODATE, because it is now
+ stopped, and the (software) event count does not need updating.
+** *start* is then called, and the counter is enabled.
+ With flag PERF_EF_RELOAD, it writes an appropriate value to the counter (check
+ previous section for detail).
+ Nothing is written if the flag does not contain PERF_EF_RELOAD.
+ The state now is reset to none, because it is neither stopped nor updated
+ (the counting already started)
+* When being context-switched out, *del* is called. It then checks out all the
+ events in the PMU and calls *stop* to update their counts.
+** *stop* is called by *del*
+ and the perf core with flag PERF_EF_UPDATE, and it often shares the same
+ subroutine as *read* with the same logic.
+ The state changes to PERF_HES_STOPPED and PERF_HES_UPTODATE, again.
+
+** Life cycle of these two pairs: *add* and *del* are called repeatedly as
+ tasks switch in-and-out; *start* and *stop* is also called when the perf core
+ needs a quick stop-and-start, for instance, when the interrupt period is being
+ adjusted.
+
+Current implementation is sufficient for now and can be easily extended to
+features in the future.
+
+A. Related Structures
+---------------------
+
+* struct pmu: include/linux/perf_event.h
+* struct riscv_pmu: arch/riscv/include/asm/perf_event.h
+
+ Both structures are designed to be read-only.
+
+ *struct pmu* defines some function pointer interfaces, and most of them take
+*struct perf_event* as a main argument, dealing with perf events according to
+perf's internal state machine (check kernel/events/core.c for details).
+
+ *struct riscv_pmu* defines PMU-specific parameters. The naming follows the
+convention of all other architectures.
+
+* struct perf_event: include/linux/perf_event.h
+* struct hw_perf_event
+
+ The generic structure that represents perf events, and the hardware-related
+details.
+
+* struct riscv_hw_events: arch/riscv/include/asm/perf_event.h
+
+ The structure that holds the status of events, has two fixed members:
+the number of events and the array of the events.
+
+References
+----------
+
+[1] https://github.com/riscv/riscv-linux/pull/124
+[2] https://groups.google.com/a/groups.riscv.org/forum/#!topic/sw-dev/f19TmCNP6yA
--
2.17.0
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH v4 0/2] perf: riscv: Preliminary Perf Event Support on RISC-V
From: Alan Kao @ 2018-04-18 2:12 UTC (permalink / raw)
To: Palmer Dabbelt, Albert Ou, Peter Zijlstra, Ingo Molnar,
Arnaldo Carvalho de Melo, Alexander Shishkin, Jiri Olsa,
Namhyung Kim, Alex Solomatnikov, Jonathan Corbet, linux-riscv,
linux-doc, linux-kernel
Cc: Alan Kao, Greentime Hu, Nick Hu
This implements the baseline PMU for RISC-V platforms.
To ease future PMU portings, a guide is also written, containing
perf concepts, arch porting practices and some hints.
Changes in v4:
- Fix several compilation errors. Sorry for that.
- Raise a warning in the write_counter body.
Changes in v3:
- Fix typos in the document.
- Change the initialization routine from statically assigning PMU to
device-tree-based methods, and set default to the PMU proposed in
this patch.
Changes in v2:
- Fix the bug reported by Alex, which was caused by not sufficient
initialization. Check https://lkml.org/lkml/2018/3/31/251 for the
discussion.
Alan Kao (2):
perf: riscv: preliminary RISC-V support
perf: riscv: Add Document for Future Porting Guide
Documentation/riscv/pmu.txt | 249 ++++++++++++++
arch/riscv/Kconfig | 13 +
arch/riscv/include/asm/perf_event.h | 79 ++++-
arch/riscv/kernel/Makefile | 1 +
arch/riscv/kernel/perf_event.c | 482 ++++++++++++++++++++++++++++
5 files changed, 820 insertions(+), 4 deletions(-)
create mode 100644 Documentation/riscv/pmu.txt
create mode 100644 arch/riscv/kernel/perf_event.c
--
2.17.0
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH v2 7/7] ocxl: Document new OCXL IOCTLs
From: Alastair D'Silva @ 2018-04-18 1:08 UTC (permalink / raw)
To: linuxppc-dev
Cc: linux-kernel, linux-doc, mikey, vaibhav, aneesh.kumar, malat,
felix, pombredanne, sukadev, npiggin, gregkh, arnd,
andrew.donnellan, fbarrat, corbet, Alastair D'Silva
In-Reply-To: <20180418010810.30937-1-alastair@au1.ibm.com>
From: Alastair D'Silva <alastair@d-silva.org>
Signed-off-by: Alastair D'Silva <alastair@d-silva.org>
---
Documentation/accelerators/ocxl.rst | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/Documentation/accelerators/ocxl.rst b/Documentation/accelerators/ocxl.rst
index 7904adcc07fd..3b8d3b99795c 100644
--- a/Documentation/accelerators/ocxl.rst
+++ b/Documentation/accelerators/ocxl.rst
@@ -157,6 +157,17 @@ OCXL_IOCTL_GET_METADATA:
Obtains configuration information from the card, such at the size of
MMIO areas, the AFU version, and the PASID for the current context.
+OCXL_IOCTL_ENABLE_P9_WAIT:
+
+ Allows the AFU to wake a userspace thread executing 'wait'. Returns
+ information to userspace to allow it to configure the AFU. Note that
+ this is only available on Power 9.
+
+OCXL_IOCTL_GET_FEATURES:
+
+ Reports on which CPU features that affect OpenCAPI are usable from
+ userspace.
+
mmap
----
--
2.14.3
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH v2 1/7] powerpc: Add TIDR CPU feature for Power9
From: Alastair D'Silva @ 2018-04-18 1:08 UTC (permalink / raw)
To: linuxppc-dev
Cc: linux-kernel, linux-doc, mikey, vaibhav, aneesh.kumar, malat,
felix, pombredanne, sukadev, npiggin, gregkh, arnd,
andrew.donnellan, fbarrat, corbet, Alastair D'Silva
In-Reply-To: <20180418010810.30937-1-alastair@au1.ibm.com>
From: Alastair D'Silva <alastair@d-silva.org>
This patch adds a CPU feature bit to show whether the CPU has
the TIDR register available, enabling as_notify/wait in userspace.
Signed-off-by: Alastair D'Silva <alastair@d-silva.org>
---
arch/powerpc/include/asm/cputable.h | 3 ++-
arch/powerpc/kernel/dt_cpu_ftrs.c | 1 +
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h
index 4e332f3531c5..54c4cbbe57b4 100644
--- a/arch/powerpc/include/asm/cputable.h
+++ b/arch/powerpc/include/asm/cputable.h
@@ -215,6 +215,7 @@ static inline void cpu_feature_keys_init(void) { }
#define CPU_FTR_P9_TM_HV_ASSIST LONG_ASM_CONST(0x0000100000000000)
#define CPU_FTR_P9_TM_XER_SO_BUG LONG_ASM_CONST(0x0000200000000000)
#define CPU_FTR_P9_TLBIE_BUG LONG_ASM_CONST(0x0000400000000000)
+#define CPU_FTR_P9_TIDR LONG_ASM_CONST(0x0000800000000000)
#ifndef __ASSEMBLY__
@@ -462,7 +463,7 @@ static inline void cpu_feature_keys_init(void) { }
CPU_FTR_CFAR | CPU_FTR_HVMODE | CPU_FTR_VMX_COPY | \
CPU_FTR_DBELL | CPU_FTR_HAS_PPR | CPU_FTR_ARCH_207S | \
CPU_FTR_TM_COMP | CPU_FTR_ARCH_300 | CPU_FTR_PKEY | \
- CPU_FTR_P9_TLBIE_BUG)
+ CPU_FTR_P9_TLBIE_BUG | CPU_FTR_P9_TIDR)
#define CPU_FTRS_POWER9_DD1 ((CPU_FTRS_POWER9 | CPU_FTR_POWER9_DD1) & \
(~CPU_FTR_SAO))
#define CPU_FTRS_POWER9_DD2_0 CPU_FTRS_POWER9
diff --git a/arch/powerpc/kernel/dt_cpu_ftrs.c b/arch/powerpc/kernel/dt_cpu_ftrs.c
index 11a3a4fed3fb..10f8b7f55637 100644
--- a/arch/powerpc/kernel/dt_cpu_ftrs.c
+++ b/arch/powerpc/kernel/dt_cpu_ftrs.c
@@ -722,6 +722,7 @@ static __init void cpufeatures_cpu_quirks(void)
if ((version & 0xffff0000) == 0x004e0000) {
cur_cpu_spec->cpu_features &= ~(CPU_FTR_DAWR);
cur_cpu_spec->cpu_features |= CPU_FTR_P9_TLBIE_BUG;
+ cur_cpu_spec->cpu_features |= CPU_FTR_P9_TIDR;
}
}
--
2.14.3
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH v2 2/7] powerpc: Use TIDR CPU feature to control TIDR allocation
From: Alastair D'Silva @ 2018-04-18 1:08 UTC (permalink / raw)
To: linuxppc-dev
Cc: linux-kernel, linux-doc, mikey, vaibhav, aneesh.kumar, malat,
felix, pombredanne, sukadev, npiggin, gregkh, arnd,
andrew.donnellan, fbarrat, corbet, Alastair D'Silva
In-Reply-To: <20180418010810.30937-1-alastair@au1.ibm.com>
From: Alastair D'Silva <alastair@d-silva.org>
Switch the use of TIDR on it's CPU feature, rather than assuming it
is available based on architecture.
Signed-off-by: Alastair D'Silva <alastair@d-silva.org>
---
arch/powerpc/kernel/process.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 1237f13fed51..3b00da47699b 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -1154,7 +1154,7 @@ static inline void restore_sprs(struct thread_struct *old_thread,
mtspr(SPRN_TAR, new_thread->tar);
}
- if (cpu_has_feature(CPU_FTR_ARCH_300) &&
+ if (cpu_has_feature(CPU_FTR_P9_TIDR) &&
old_thread->tidr != new_thread->tidr)
mtspr(SPRN_TIDR, new_thread->tidr);
#endif
@@ -1570,7 +1570,7 @@ void clear_thread_tidr(struct task_struct *t)
if (!t->thread.tidr)
return;
- if (!cpu_has_feature(CPU_FTR_ARCH_300)) {
+ if (!cpu_has_feature(CPU_FTR_P9_TIDR)) {
WARN_ON_ONCE(1);
return;
}
@@ -1593,7 +1593,7 @@ int set_thread_tidr(struct task_struct *t)
{
int rc;
- if (!cpu_has_feature(CPU_FTR_ARCH_300))
+ if (!cpu_has_feature(CPU_FTR_P9_TIDR))
return -EINVAL;
if (t != current)
--
2.14.3
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH v2 6/7] ocxl: Add an IOCTL so userspace knows what CPU features are available
From: Alastair D'Silva @ 2018-04-18 1:08 UTC (permalink / raw)
To: linuxppc-dev
Cc: linux-kernel, linux-doc, mikey, vaibhav, aneesh.kumar, malat,
felix, pombredanne, sukadev, npiggin, gregkh, arnd,
andrew.donnellan, fbarrat, corbet, Alastair D'Silva
In-Reply-To: <20180418010810.30937-1-alastair@au1.ibm.com>
From: Alastair D'Silva <alastair@d-silva.org>
In order for a userspace AFU driver to call the Power9 specific
OCXL_IOCTL_ENABLE_P9_WAIT, it needs to verify that it can actually
make that call.
Signed-off-by: Alastair D'Silva <alastair@d-silva.org>
---
Documentation/accelerators/ocxl.rst | 1 -
drivers/misc/ocxl/file.c | 25 +++++++++++++++++++++++++
include/uapi/misc/ocxl.h | 4 ++++
3 files changed, 29 insertions(+), 1 deletion(-)
diff --git a/Documentation/accelerators/ocxl.rst b/Documentation/accelerators/ocxl.rst
index ddcc58d01cfb..7904adcc07fd 100644
--- a/Documentation/accelerators/ocxl.rst
+++ b/Documentation/accelerators/ocxl.rst
@@ -157,7 +157,6 @@ OCXL_IOCTL_GET_METADATA:
Obtains configuration information from the card, such at the size of
MMIO areas, the AFU version, and the PASID for the current context.
-
mmap
----
diff --git a/drivers/misc/ocxl/file.c b/drivers/misc/ocxl/file.c
index eb409a469f21..33ae46ce0a8a 100644
--- a/drivers/misc/ocxl/file.c
+++ b/drivers/misc/ocxl/file.c
@@ -168,12 +168,32 @@ static long afu_ioctl_enable_p9_wait(struct ocxl_context *ctx,
}
#endif
+
+static long afu_ioctl_get_features(struct ocxl_context *ctx,
+ struct ocxl_ioctl_features __user *uarg)
+{
+ struct ocxl_ioctl_features arg;
+
+ memset(&arg, 0, sizeof(arg));
+
+#ifdef CONFIG_PPC64
+ if (cpu_has_feature(CPU_FTR_P9_TIDR))
+ arg.flags[0] |= OCXL_IOCTL_FEATURES_FLAGS0_P9_WAIT;
+#endif
+
+ if (copy_to_user(uarg, &arg, sizeof(arg)))
+ return -EFAULT;
+
+ return 0;
+}
+
#define CMD_STR(x) (x == OCXL_IOCTL_ATTACH ? "ATTACH" : \
x == OCXL_IOCTL_IRQ_ALLOC ? "IRQ_ALLOC" : \
x == OCXL_IOCTL_IRQ_FREE ? "IRQ_FREE" : \
x == OCXL_IOCTL_IRQ_SET_FD ? "IRQ_SET_FD" : \
x == OCXL_IOCTL_GET_METADATA ? "GET_METADATA" : \
x == OCXL_IOCTL_ENABLE_P9_WAIT ? "ENABLE_P9_WAIT" : \
+ x == OCXL_IOCTL_GET_FEATURES ? "GET_FEATURES" : \
"UNKNOWN")
static long afu_ioctl(struct file *file, unsigned int cmd,
@@ -239,6 +259,11 @@ static long afu_ioctl(struct file *file, unsigned int cmd,
break;
#endif
+ case OCXL_IOCTL_GET_FEATURES:
+ rc = afu_ioctl_get_features(ctx,
+ (struct ocxl_ioctl_features __user *) args);
+ break;
+
default:
rc = -EINVAL;
}
diff --git a/include/uapi/misc/ocxl.h b/include/uapi/misc/ocxl.h
index 8d2748e69c84..bb80f294b429 100644
--- a/include/uapi/misc/ocxl.h
+++ b/include/uapi/misc/ocxl.h
@@ -55,6 +55,9 @@ struct ocxl_ioctl_p9_wait {
__u64 reserved3[3];
};
+#define OCXL_IOCTL_FEATURES_FLAGS0_P9_WAIT 0x01
+struct ocxl_ioctl_features {
+ __u64 flags[4];
};
struct ocxl_ioctl_irq_fd {
@@ -72,5 +75,6 @@ struct ocxl_ioctl_irq_fd {
#define OCXL_IOCTL_IRQ_SET_FD _IOW(OCXL_MAGIC, 0x13, struct ocxl_ioctl_irq_fd)
#define OCXL_IOCTL_GET_METADATA _IOR(OCXL_MAGIC, 0x14, struct ocxl_ioctl_metadata)
#define OCXL_IOCTL_ENABLE_P9_WAIT _IOR(OCXL_MAGIC, 0x15, struct ocxl_ioctl_p9_wait)
+#define OCXL_IOCTL_GET_FEATURES _IOR(OCXL_MAGIC, 0x16, struct ocxl_ioctl_platform)
#endif /* _UAPI_MISC_OCXL_H */
--
2.14.3
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH v2 5/7] ocxl: Expose the thread_id needed for wait on p9
From: Alastair D'Silva @ 2018-04-18 1:08 UTC (permalink / raw)
To: linuxppc-dev
Cc: linux-kernel, linux-doc, mikey, vaibhav, aneesh.kumar, malat,
felix, pombredanne, sukadev, npiggin, gregkh, arnd,
andrew.donnellan, fbarrat, corbet, Alastair D'Silva
In-Reply-To: <20180418010810.30937-1-alastair@au1.ibm.com>
From: Alastair D'Silva <alastair@d-silva.org>
In order to successfully issue as_notify, an AFU needs to know the TID
to notify, which in turn means that this information should be
available in userspace so it can be communicated to the AFU.
Signed-off-by: Alastair D'Silva <alastair@d-silva.org>
---
drivers/misc/ocxl/context.c | 5 +++-
drivers/misc/ocxl/file.c | 53 +++++++++++++++++++++++++++++++++++++++
drivers/misc/ocxl/link.c | 36 ++++++++++++++++++++++++++
drivers/misc/ocxl/ocxl_internal.h | 1 +
include/misc/ocxl.h | 9 +++++++
include/uapi/misc/ocxl.h | 10 ++++++++
6 files changed, 113 insertions(+), 1 deletion(-)
diff --git a/drivers/misc/ocxl/context.c b/drivers/misc/ocxl/context.c
index 909e8807824a..95f74623113e 100644
--- a/drivers/misc/ocxl/context.c
+++ b/drivers/misc/ocxl/context.c
@@ -34,6 +34,8 @@ int ocxl_context_init(struct ocxl_context *ctx, struct ocxl_afu *afu,
mutex_init(&ctx->xsl_error_lock);
mutex_init(&ctx->irq_lock);
idr_init(&ctx->irq_idr);
+ ctx->tidr = 0;
+
/*
* Keep a reference on the AFU to make sure it's valid for the
* duration of the life of the context
@@ -65,6 +67,7 @@ int ocxl_context_attach(struct ocxl_context *ctx, u64 amr)
{
int rc;
+ // Locks both status & tidr
mutex_lock(&ctx->status_mutex);
if (ctx->status != OPENED) {
rc = -EIO;
@@ -72,7 +75,7 @@ int ocxl_context_attach(struct ocxl_context *ctx, u64 amr)
}
rc = ocxl_link_add_pe(ctx->afu->fn->link, ctx->pasid,
- current->mm->context.id, 0, amr, current->mm,
+ current->mm->context.id, ctx->tidr, amr, current->mm,
xsl_fault_error, ctx);
if (rc)
goto out;
diff --git a/drivers/misc/ocxl/file.c b/drivers/misc/ocxl/file.c
index 038509e5d031..eb409a469f21 100644
--- a/drivers/misc/ocxl/file.c
+++ b/drivers/misc/ocxl/file.c
@@ -5,6 +5,8 @@
#include <linux/sched/signal.h>
#include <linux/uaccess.h>
#include <uapi/misc/ocxl.h>
+#include <asm/reg.h>
+#include <asm/switch_to.h>
#include "ocxl_internal.h"
@@ -123,11 +125,55 @@ static long afu_ioctl_get_metadata(struct ocxl_context *ctx,
return 0;
}
+#ifdef CONFIG_PPC64
+static long afu_ioctl_enable_p9_wait(struct ocxl_context *ctx,
+ struct ocxl_ioctl_p9_wait __user *uarg)
+{
+ struct ocxl_ioctl_p9_wait arg;
+
+ memset(&arg, 0, sizeof(arg));
+
+ if (cpu_has_feature(CPU_FTR_P9_TIDR)) {
+ enum ocxl_context_status status;
+
+ // Locks both status & tidr
+ mutex_lock(&ctx->status_mutex);
+ if (!ctx->tidr) {
+ if (set_thread_tidr(current))
+ return -ENOENT;
+
+ ctx->tidr = current->thread.tidr;
+ }
+
+ status = ctx->status;
+ mutex_unlock(&ctx->status_mutex);
+
+ if (status == ATTACHED) {
+ int rc;
+ struct link *link = ctx->afu->fn->link;
+
+ rc = ocxl_link_update_pe(link, ctx->pasid, ctx->tidr);
+ if (rc)
+ return rc;
+ }
+
+ arg.thread_id = ctx->tidr;
+ } else
+ return -ENOENT;
+
+ if (copy_to_user(uarg, &arg, sizeof(arg)))
+ return -EFAULT;
+
+ return 0;
+}
+#endif
+
#define CMD_STR(x) (x == OCXL_IOCTL_ATTACH ? "ATTACH" : \
x == OCXL_IOCTL_IRQ_ALLOC ? "IRQ_ALLOC" : \
x == OCXL_IOCTL_IRQ_FREE ? "IRQ_FREE" : \
x == OCXL_IOCTL_IRQ_SET_FD ? "IRQ_SET_FD" : \
x == OCXL_IOCTL_GET_METADATA ? "GET_METADATA" : \
+ x == OCXL_IOCTL_ENABLE_P9_WAIT ? "ENABLE_P9_WAIT" : \
"UNKNOWN")
static long afu_ioctl(struct file *file, unsigned int cmd,
@@ -186,6 +232,13 @@ static long afu_ioctl(struct file *file, unsigned int cmd,
(struct ocxl_ioctl_metadata __user *) args);
break;
+#ifdef CONFIG_PPC64
+ case OCXL_IOCTL_ENABLE_P9_WAIT:
+ rc = afu_ioctl_enable_p9_wait(ctx,
+ (struct ocxl_ioctl_p9_wait __user *) args);
+ break;
+#endif
+
default:
rc = -EINVAL;
}
diff --git a/drivers/misc/ocxl/link.c b/drivers/misc/ocxl/link.c
index 656e8610eec2..88876ae8f330 100644
--- a/drivers/misc/ocxl/link.c
+++ b/drivers/misc/ocxl/link.c
@@ -544,6 +544,42 @@ int ocxl_link_add_pe(void *link_handle, int pasid, u32 pidr, u32 tidr,
}
EXPORT_SYMBOL_GPL(ocxl_link_add_pe);
+int ocxl_link_update_pe(void *link_handle, int pasid, __u16 tid)
+{
+ struct link *link = (struct link *) link_handle;
+ struct spa *spa = link->spa;
+ struct ocxl_process_element *pe;
+ int pe_handle, rc;
+
+ if (pasid > SPA_PASID_MAX)
+ return -EINVAL;
+
+ pe_handle = pasid & SPA_PE_MASK;
+ pe = spa->spa_mem + pe_handle;
+
+ mutex_lock(&spa->spa_lock);
+
+ pe->tid = tid;
+
+ /*
+ * The barrier makes sure the PE is updated
+ * before we clear the NPU context cache below, so that the
+ * old PE cannot be reloaded erroneously.
+ */
+ mb();
+
+ /*
+ * hook to platform code
+ * On powerpc, the entry needs to be cleared from the context
+ * cache of the NPU.
+ */
+ rc = pnv_ocxl_spa_remove_pe_from_cache(link->platform_data, pe_handle);
+ WARN_ON(rc);
+
+ mutex_unlock(&spa->spa_lock);
+ return rc;
+}
+
int ocxl_link_remove_pe(void *link_handle, int pasid)
{
struct link *link = (struct link *) link_handle;
diff --git a/drivers/misc/ocxl/ocxl_internal.h b/drivers/misc/ocxl/ocxl_internal.h
index 5d421824afd9..6c6d4e61888e 100644
--- a/drivers/misc/ocxl/ocxl_internal.h
+++ b/drivers/misc/ocxl/ocxl_internal.h
@@ -77,6 +77,7 @@ struct ocxl_context {
struct ocxl_xsl_error xsl_error;
struct mutex irq_lock;
struct idr irq_idr;
+ __u16 tidr; // Thread ID used for P9 wait implementation
};
struct ocxl_process_element {
diff --git a/include/misc/ocxl.h b/include/misc/ocxl.h
index 51ccf76db293..9ff6ddc28e22 100644
--- a/include/misc/ocxl.h
+++ b/include/misc/ocxl.h
@@ -188,6 +188,15 @@ extern int ocxl_link_add_pe(void *link_handle, int pasid, u32 pidr, u32 tidr,
void (*xsl_err_cb)(void *data, u64 addr, u64 dsisr),
void *xsl_err_data);
+/**
+ * Update values within a Process Element
+ *
+ * link_handle: the link handle associated with the process element
+ * pasid: the PASID for the AFU context
+ * tid: the new thread id for the process element
+ */
+extern int ocxl_link_update_pe(void *link_handle, int pasid, __u16 tid);
+
/*
* Remove a Process Element from the Shared Process Area for a link
*/
diff --git a/include/uapi/misc/ocxl.h b/include/uapi/misc/ocxl.h
index 0af83d80fb3e..8d2748e69c84 100644
--- a/include/uapi/misc/ocxl.h
+++ b/include/uapi/misc/ocxl.h
@@ -48,6 +48,15 @@ struct ocxl_ioctl_metadata {
__u64 reserved[13]; // Total of 16*u64
};
+struct ocxl_ioctl_p9_wait {
+ __u16 thread_id; // The thread ID required to wake this thread
+ __u16 reserved1;
+ __u32 reserved2;
+ __u64 reserved3[3];
+};
+
+};
+
struct ocxl_ioctl_irq_fd {
__u64 irq_offset;
__s32 eventfd;
@@ -62,5 +71,6 @@ struct ocxl_ioctl_irq_fd {
#define OCXL_IOCTL_IRQ_FREE _IOW(OCXL_MAGIC, 0x12, __u64)
#define OCXL_IOCTL_IRQ_SET_FD _IOW(OCXL_MAGIC, 0x13, struct ocxl_ioctl_irq_fd)
#define OCXL_IOCTL_GET_METADATA _IOR(OCXL_MAGIC, 0x14, struct ocxl_ioctl_metadata)
+#define OCXL_IOCTL_ENABLE_P9_WAIT _IOR(OCXL_MAGIC, 0x15, struct ocxl_ioctl_p9_wait)
#endif /* _UAPI_MISC_OCXL_H */
--
2.14.3
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH v2 3/7] powerpc: use task_pid_nr() for TID allocation
From: Alastair D'Silva @ 2018-04-18 1:08 UTC (permalink / raw)
To: linuxppc-dev
Cc: linux-kernel, linux-doc, mikey, vaibhav, aneesh.kumar, malat,
felix, pombredanne, sukadev, npiggin, gregkh, arnd,
andrew.donnellan, fbarrat, corbet, Alastair D'Silva
In-Reply-To: <20180418010810.30937-1-alastair@au1.ibm.com>
From: Alastair D'Silva <alastair@d-silva.org>
The current implementation of TID allocation, using a global IDR, may
result in an errant process starving the system of available TIDs.
Instead, use task_pid_nr(), as mentioned by the original author. The
scenario described which prevented it's use is not applicable, as
set_thread_tidr can only be called after the task struct has been
populated.
Signed-off-by: Alastair D'Silva <alastair@d-silva.org>
---
arch/powerpc/include/asm/switch_to.h | 1 -
arch/powerpc/kernel/process.c | 97 +-----------------------------------
2 files changed, 1 insertion(+), 97 deletions(-)
diff --git a/arch/powerpc/include/asm/switch_to.h b/arch/powerpc/include/asm/switch_to.h
index be8c9fa23983..5b03d8a82409 100644
--- a/arch/powerpc/include/asm/switch_to.h
+++ b/arch/powerpc/include/asm/switch_to.h
@@ -94,6 +94,5 @@ static inline void clear_task_ebb(struct task_struct *t)
extern int set_thread_uses_vas(void);
extern int set_thread_tidr(struct task_struct *t);
-extern void clear_thread_tidr(struct task_struct *t);
#endif /* _ASM_POWERPC_SWITCH_TO_H */
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 3b00da47699b..87f047fd2762 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -1496,103 +1496,12 @@ int set_thread_uses_vas(void)
}
#ifdef CONFIG_PPC64
-static DEFINE_SPINLOCK(vas_thread_id_lock);
-static DEFINE_IDA(vas_thread_ida);
-
-/*
- * We need to assign a unique thread id to each thread in a process.
- *
- * This thread id, referred to as TIDR, and separate from the Linux's tgid,
- * is intended to be used to direct an ASB_Notify from the hardware to the
- * thread, when a suitable event occurs in the system.
- *
- * One such event is a "paste" instruction in the context of Fast Thread
- * Wakeup (aka Core-to-core wake up in the Virtual Accelerator Switchboard
- * (VAS) in POWER9.
- *
- * To get a unique TIDR per process we could simply reuse task_pid_nr() but
- * the problem is that task_pid_nr() is not yet available copy_thread() is
- * called. Fixing that would require changing more intrusive arch-neutral
- * code in code path in copy_process()?.
- *
- * Further, to assign unique TIDRs within each process, we need an atomic
- * field (or an IDR) in task_struct, which again intrudes into the arch-
- * neutral code. So try to assign globally unique TIDRs for now.
- *
- * NOTE: TIDR 0 indicates that the thread does not need a TIDR value.
- * For now, only threads that expect to be notified by the VAS
- * hardware need a TIDR value and we assign values > 0 for those.
- */
-#define MAX_THREAD_CONTEXT ((1 << 16) - 1)
-static int assign_thread_tidr(void)
-{
- int index;
- int err;
- unsigned long flags;
-
-again:
- if (!ida_pre_get(&vas_thread_ida, GFP_KERNEL))
- return -ENOMEM;
-
- spin_lock_irqsave(&vas_thread_id_lock, flags);
- err = ida_get_new_above(&vas_thread_ida, 1, &index);
- spin_unlock_irqrestore(&vas_thread_id_lock, flags);
-
- if (err == -EAGAIN)
- goto again;
- else if (err)
- return err;
-
- if (index > MAX_THREAD_CONTEXT) {
- spin_lock_irqsave(&vas_thread_id_lock, flags);
- ida_remove(&vas_thread_ida, index);
- spin_unlock_irqrestore(&vas_thread_id_lock, flags);
- return -ENOMEM;
- }
-
- return index;
-}
-
-static void free_thread_tidr(int id)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&vas_thread_id_lock, flags);
- ida_remove(&vas_thread_ida, id);
- spin_unlock_irqrestore(&vas_thread_id_lock, flags);
-}
-
-/*
- * Clear any TIDR value assigned to this thread.
- */
-void clear_thread_tidr(struct task_struct *t)
-{
- if (!t->thread.tidr)
- return;
-
- if (!cpu_has_feature(CPU_FTR_P9_TIDR)) {
- WARN_ON_ONCE(1);
- return;
- }
-
- mtspr(SPRN_TIDR, 0);
- free_thread_tidr(t->thread.tidr);
- t->thread.tidr = 0;
-}
-
-void arch_release_task_struct(struct task_struct *t)
-{
- clear_thread_tidr(t);
-}
-
/*
* Assign a unique TIDR (thread id) for task @t and set it in the thread
* structure. For now, we only support setting TIDR for 'current' task.
*/
int set_thread_tidr(struct task_struct *t)
{
- int rc;
-
if (!cpu_has_feature(CPU_FTR_P9_TIDR))
return -EINVAL;
@@ -1602,11 +1511,7 @@ int set_thread_tidr(struct task_struct *t)
if (t->thread.tidr)
return 0;
- rc = assign_thread_tidr();
- if (rc < 0)
- return rc;
-
- t->thread.tidr = rc;
+ t->thread.tidr = (u16)task_pid_nr(t);
mtspr(SPRN_TIDR, t->thread.tidr);
return 0;
--
2.14.3
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH v2 0/7] ocxl: Implement Power9 as_notify/wait for OpenCAPI
From: Alastair D'Silva @ 2018-04-18 1:08 UTC (permalink / raw)
To: linuxppc-dev
Cc: linux-kernel, linux-doc, mikey, vaibhav, aneesh.kumar, malat,
felix, pombredanne, sukadev, npiggin, gregkh, arnd,
andrew.donnellan, fbarrat, corbet, Alastair D'Silva
In-Reply-To: <20180417020950.21446-1-alastair@au1.ibm.com>
From: Alastair D'Silva <alastair@d-silva.org>
The Power 9 as_notify/wait feature provides a lower latency way to
signal a thread that work is complete. This series enables the use of
this feature from OpenCAPI adapters, as well as addressing a potential
starvation issue when allocating thread IDs.
Changelog:
v2:
Rename get_platform IOCTL to get_features
Move stray edit from patch 1 to patch 3
Alastair D'Silva (7):
powerpc: Add TIDR CPU feature for Power9
powerpc: Use TIDR CPU feature to control TIDR allocation
powerpc: use task_pid_nr() for TID allocation
ocxl: Rename pnv_ocxl_spa_remove_pe to clarify it's action
ocxl: Expose the thread_id needed for wait on p9
ocxl: Add an IOCTL so userspace knows what CPU features are available
ocxl: Document new OCXL IOCTLs
Documentation/accelerators/ocxl.rst | 10 ++++
arch/powerpc/include/asm/cputable.h | 3 +-
arch/powerpc/include/asm/pnv-ocxl.h | 2 +-
arch/powerpc/include/asm/switch_to.h | 1 -
arch/powerpc/kernel/dt_cpu_ftrs.c | 1 +
arch/powerpc/kernel/process.c | 101 +---------------------------------
arch/powerpc/platforms/powernv/ocxl.c | 4 +-
drivers/misc/ocxl/context.c | 5 +-
drivers/misc/ocxl/file.c | 78 ++++++++++++++++++++++++++
drivers/misc/ocxl/link.c | 38 ++++++++++++-
drivers/misc/ocxl/ocxl_internal.h | 1 +
include/misc/ocxl.h | 9 +++
include/uapi/misc/ocxl.h | 14 +++++
13 files changed, 162 insertions(+), 105 deletions(-)
--
2.14.3
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH v2 4/7] ocxl: Rename pnv_ocxl_spa_remove_pe to clarify it's action
From: Alastair D'Silva @ 2018-04-18 1:08 UTC (permalink / raw)
To: linuxppc-dev
Cc: linux-kernel, linux-doc, mikey, vaibhav, aneesh.kumar, malat,
felix, pombredanne, sukadev, npiggin, gregkh, arnd,
andrew.donnellan, fbarrat, corbet, Alastair D'Silva
In-Reply-To: <20180418010810.30937-1-alastair@au1.ibm.com>
From: Alastair D'Silva <alastair@d-silva.org>
The function removes the process element from NPU cache.
Signed-off-by: Alastair D'Silva <alastair@d-silva.org>
---
arch/powerpc/include/asm/pnv-ocxl.h | 2 +-
arch/powerpc/platforms/powernv/ocxl.c | 4 ++--
drivers/misc/ocxl/link.c | 2 +-
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/arch/powerpc/include/asm/pnv-ocxl.h b/arch/powerpc/include/asm/pnv-ocxl.h
index f6945d3bc971..208b5503f4ed 100644
--- a/arch/powerpc/include/asm/pnv-ocxl.h
+++ b/arch/powerpc/include/asm/pnv-ocxl.h
@@ -28,7 +28,7 @@ extern int pnv_ocxl_map_xsl_regs(struct pci_dev *dev, void __iomem **dsisr,
extern int pnv_ocxl_spa_setup(struct pci_dev *dev, void *spa_mem, int PE_mask,
void **platform_data);
extern void pnv_ocxl_spa_release(void *platform_data);
-extern int pnv_ocxl_spa_remove_pe(void *platform_data, int pe_handle);
+extern int pnv_ocxl_spa_remove_pe_from_cache(void *platform_data, int pe_handle);
extern int pnv_ocxl_alloc_xive_irq(u32 *irq, u64 *trigger_addr);
extern void pnv_ocxl_free_xive_irq(u32 irq);
diff --git a/arch/powerpc/platforms/powernv/ocxl.c b/arch/powerpc/platforms/powernv/ocxl.c
index fa9b53af3c7b..8c65aacda9c8 100644
--- a/arch/powerpc/platforms/powernv/ocxl.c
+++ b/arch/powerpc/platforms/powernv/ocxl.c
@@ -475,7 +475,7 @@ void pnv_ocxl_spa_release(void *platform_data)
}
EXPORT_SYMBOL_GPL(pnv_ocxl_spa_release);
-int pnv_ocxl_spa_remove_pe(void *platform_data, int pe_handle)
+int pnv_ocxl_spa_remove_pe_from_cache(void *platform_data, int pe_handle)
{
struct spa_data *data = (struct spa_data *) platform_data;
int rc;
@@ -483,7 +483,7 @@ int pnv_ocxl_spa_remove_pe(void *platform_data, int pe_handle)
rc = opal_npu_spa_clear_cache(data->phb_opal_id, data->bdfn, pe_handle);
return rc;
}
-EXPORT_SYMBOL_GPL(pnv_ocxl_spa_remove_pe);
+EXPORT_SYMBOL_GPL(pnv_ocxl_spa_remove_pe_from_cache);
int pnv_ocxl_alloc_xive_irq(u32 *irq, u64 *trigger_addr)
{
diff --git a/drivers/misc/ocxl/link.c b/drivers/misc/ocxl/link.c
index f30790582dc0..656e8610eec2 100644
--- a/drivers/misc/ocxl/link.c
+++ b/drivers/misc/ocxl/link.c
@@ -599,7 +599,7 @@ int ocxl_link_remove_pe(void *link_handle, int pasid)
* On powerpc, the entry needs to be cleared from the context
* cache of the NPU.
*/
- rc = pnv_ocxl_spa_remove_pe(link->platform_data, pe_handle);
+ rc = pnv_ocxl_spa_remove_pe_from_cache(link->platform_data, pe_handle);
WARN_ON(rc);
pe_data = radix_tree_delete(&spa->pe_tree, pe_handle);
--
2.14.3
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* Re: [PATCH bpf-next v3 2/8] bpf: add documentation for eBPF helpers (01-11)
From: Alexei Starovoitov @ 2018-04-18 1:04 UTC (permalink / raw)
To: Quentin Monnet; +Cc: daniel, ast, netdev, oss-drivers, linux-doc, linux-man
In-Reply-To: <20180417143438.7018-3-quentin.monnet@netronome.com>
On Tue, Apr 17, 2018 at 03:34:32PM +0100, Quentin Monnet wrote:
> Add documentation for eBPF helper functions to bpf.h user header file.
> This documentation can be parsed with the Python script provided in
> another commit of the patch series, in order to provide a RST document
> that can later be converted into a man page.
>
> The objective is to make the documentation easily understandable and
> accessible to all eBPF developers, including beginners.
>
> This patch contains descriptions for the following helper functions, all
> written by Alexei:
>
> - bpf_map_lookup_elem()
> - bpf_map_update_elem()
> - bpf_map_delete_elem()
> - bpf_probe_read()
> - bpf_ktime_get_ns()
> - bpf_trace_printk()
> - bpf_skb_store_bytes()
> - bpf_l3_csum_replace()
> - bpf_l4_csum_replace()
> - bpf_tail_call()
> - bpf_clone_redirect()
>
> v3:
> - bpf_map_lookup_elem(): Fix description of restrictions for flags
> related to the existence of the entry.
> - bpf_trace_printk(): State that trace_pipe can be configured. Fix
> return value in case an unknown format specifier is met. Add a note on
> kernel log notice when the helper is used. Edit example.
> - bpf_tail_call(): Improve comment on stack inheritance.
> - bpf_clone_redirect(): Improve description of BPF_F_INGRESS flag.
>
> Cc: Alexei Starovoitov <ast@kernel.org>
> Signed-off-by: Quentin Monnet <quentin.monnet@netronome.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v3 04/10] Documentations: dt-bindings: Add a document of PECI adapter driver for Aspeed AST24xx/25xx SoCs
From: Jae Hyun Yoo @ 2018-04-17 22:06 UTC (permalink / raw)
To: Rob Herring
Cc: Alan Cox, Andrew Jeffery, Andrew Lunn, Andy Shevchenko,
Arnd Bergmann, Benjamin Herrenschmidt, Fengguang Wu, Greg KH,
Guenter Roeck, Haiyue Wang, James Feist, Jason M Biils,
Jean Delvare, Joel Stanley, Julia Cartwright, Miguel Ojeda,
Milton Miller II, Pavel Machek, Randy Dunlap, Stef van Os,
Sumeet R Pawnikar, Vernon Mauery, linux-kernel@vger.kernel.org,
linux-doc, devicetree, Linux HWMON List,
moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
OpenBMC Maillist
In-Reply-To: <f07623c4-5f0c-4ab1-f761-44bd702bbdf0@linux.intel.com>
On 4/17/2018 11:16 AM, Jae Hyun Yoo wrote:
> On 4/17/2018 6:16 AM, Rob Herring wrote:
>> On Mon, Apr 16, 2018 at 6:12 PM, Jae Hyun Yoo
>> <jae.hyun.yoo@linux.intel.com> wrote:
>>> On 4/16/2018 11:10 AM, Rob Herring wrote:
>>>>
>>>> On Tue, Apr 10, 2018 at 11:32:06AM -0700, Jae Hyun Yoo wrote:
>>>>>
>>>>> This commit adds a dt-bindings document of PECI adapter driver for
>>>>> Aspeed
>>>>> AST24xx/25xx SoCs.
>>
>> [...]
>>
>>>>> +- clocks : Should contain clock source for PECI
>>>>> controller.
>>>>> + Should reference clkin.
>>>>> +- clock_frequency : Should contain the operation frequency of PECI
>>>>> controller
>>>>> + in units of Hz.
>>>>> + 187500 ~ 24000000
>>>>
>>>>
>>>> This is the frequency of the bus or used to derive it? It would be
>>>> better to specify the bus frequency instead and have the driver
>>>> calculate its internal freq. And then use "bus-frequency" instead.
>>>>
>>>
>>> I agree with you. Actually, it is being used for operation frequency
>>> setting
>>> of PECI controller module in SoC so it's different from the meaning of
>>> "bus-frequency". I'll change it to "operation-frequency".
>>
>> No, now you've gone from a standard property name to something custom.
>> Why do you need to set the frequency in DT if it is not related to the
>> interface frequency?
>>
>> Rob
>>
>
> Actually, the interface frequency is affected by the operation frequency
> but there is no description of its relationship in datasheet. I'll check
> again about the detail to ASPEED chip vendor and will use
> 'bus-frequency' if available.
>
I investigated it more deeply. Basically, by the spec, PECI bus speed
cannot be set as a fixed speed. A PECI bus can have a wide speed range
from 2Kbps to 2Mbps which is dynamically set by a handshaking sequence
between an originator and clients called 'timing negotiation' in spec.
This timing negotiation behavior happens on every single transaction so
the bus speed also can vary on every transactions. So I'm thinking a
custom property name for it, 'peci-clk-frequency' if it is acceptable.
Thanks,
Jae
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v3 07/10] Documentation: dt-bindings: Add documents for PECI hwmon client drivers
From: Jae Hyun Yoo @ 2018-04-17 20:40 UTC (permalink / raw)
To: Rob Herring
Cc: Alan Cox, Andrew Jeffery, Andrew Lunn, Andy Shevchenko,
Arnd Bergmann, Benjamin Herrenschmidt, Fengguang Wu, Greg KH,
Guenter Roeck, Haiyue Wang, James Feist, Jason M Biils,
Jean Delvare, Joel Stanley, Julia Cartwright, Miguel Ojeda,
Milton Miller II, Pavel Machek, Randy Dunlap, Stef van Os,
Sumeet R Pawnikar, Vernon Mauery, linux-kernel, linux-doc,
devicetree, linux-hwmon, linux-arm-kernel, openbmc
In-Reply-To: <287e0fd9-b631-2602-2785-7b8aaed7a6b9@linux.intel.com>
On 4/16/2018 4:51 PM, Jae Hyun Yoo wrote:
> On 4/16/2018 4:22 PM, Jae Hyun Yoo wrote:
>> On 4/16/2018 11:14 AM, Rob Herring wrote:
>>> On Tue, Apr 10, 2018 at 11:32:09AM -0700, Jae Hyun Yoo wrote:
>>>> This commit adds dt-bindings documents for PECI cputemp and dimmtemp
>>>> client
>>>> drivers.
>>>
[...]
>>>> +Example:
>>>> + peci-bus@0 {
>>>> + #address-cells = <1>;
>>>> + #size-cells = <0>;
>>>> + < more properties >
>>>> +
>>>> + peci-dimmtemp@cpu0 {
>>>
>>> unit-address is wrong.
>>>
>>
>> Will fix it using the reg value.
>>
>>> It is a different bus from cputemp? Otherwise, you have conflicting
>>> addresses. If that's the case, probably should make it clear by showing
>>> different host adapters for each example.
>>>
>>
>> It could be the same bus with cputemp. Also, client address sharing is
>> possible by PECI core if the functionality is different. I mean,
>> cputemp and dimmtemp targeting the same client is possible case like
>> this.
>> peci-cputemp@30
>> peci-dimmtemp@30
>>
>
> Oh, I got your point. Probably, I should change these separate settings
> into one like
>
> peci-client@30 {
> compatible = "intel,peci-client";
> reg = <0x30>;
> };
>
> Then cputemp and dimmtemp drivers could refer the same compatible
> string. Will rewrite it.
>
I've checked it again and realized that it should use function based
node name like:
peci-cputemp@30
peci-dimmtemp@30
If it use the same string like 'peci-client@30', the drivers cannot be
selectively enabled. The client address sharing way is well handled in
PECI core and this way would be better for the future implementations of
other PECI functional drivers such as crash dump driver and so on. So
I'm going change the unit-address only.
Thanks,
Jae
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v3 1/2] perf: riscv: preliminary RISC-V support
From: Alex Solomatnikov @ 2018-04-17 20:35 UTC (permalink / raw)
To: Alan Kao
Cc: Palmer Dabbelt, Albert Ou, Peter Zijlstra, Ingo Molnar,
Arnaldo Carvalho de Melo, Alexander Shishkin, Jiri Olsa,
Namhyung Kim, Jonathan Corbet, linux-riscv, linux-doc,
linux-kernel, Nick Hu, Greentime Hu
In-Reply-To: <1523954340-8708-2-git-send-email-alankao@andestech.com>
On Tue, Apr 17, 2018 at 1:38 AM, Alan Kao <alankao@andestech.com> wrote:
> +static inline void write_counter(int idx, u64 value)
> +{
> + /* currently not supported */
> +}
CSR writes can be emulated: https://github.com/riscv/riscv-pk/pull/98
Or at least write_counter() should have BUG() or WARN_ONCE() or
something like that.
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v3 1/2] perf: riscv: preliminary RISC-V support
From: Alex Solomatnikov @ 2018-04-17 20:13 UTC (permalink / raw)
To: Alan Kao
Cc: Palmer Dabbelt, Albert Ou, Peter Zijlstra, Ingo Molnar,
Arnaldo Carvalho de Melo, Alexander Shishkin, Jiri Olsa,
Namhyung Kim, Jonathan Corbet, linux-riscv, linux-doc,
linux-kernel, Nick Hu, Greentime Hu
In-Reply-To: <1523954340-8708-2-git-send-email-alankao@andestech.com>
This does not compile:
/freedom-u-sdk/linux/arch/riscv/kernel/perf_event.c: In function
'riscv_pmu_stop':
/freedom-u-sdk/linux/arch/riscv/kernel/perf_event.c:258:12: error:
'const struct riscv_pmu' has no member named 'read'
riscv_pmu->read(event);
^~
/freedom-u-sdk/linux/arch/riscv/kernel/perf_event.c: In function
'riscv_pmu_add':
/freedom-u-sdk/linux/arch/riscv/kernel/perf_event.c:319:12: error:
'const struct riscv_pmu' has no member named 'start'
riscv_pmu->start(event, PERF_EF_RELOAD);
^~
/freedom-u-sdk/linux/arch/riscv/kernel/perf_event.c: In function
'riscv_pmu_del':
/freedom-u-sdk/linux/arch/riscv/kernel/perf_event.c:334:11: error:
'const struct riscv_pmu' has no member named 'stop'
riscv_pmu->stop(event, PERF_EF_UPDATE);
^~
/freedom-u-sdk/linux/arch/riscv/kernel/perf_event.c: At top level:
/freedom-u-sdk/linux/arch/riscv/kernel/perf_event.c:345:1: error:
expected identifier or '(' before '{' token
{
^
/freedom-u-sdk/linux/arch/riscv/kernel/perf_event.c: In function
'reserve_pmc_hardware':
/freedom-u-sdk/linux/arch/riscv/kernel/perf_event.c:353:15: error:
'const struct riscv_pmu' has no member named 'irq'
if (riscv_pmu->irq >=0 && riscv_pmu->handle_irq) {
^~
/freedom-u-sdk/linux/arch/riscv/kernel/perf_event.c:354:30: error:
'const struct riscv_pmu' has no member named 'irq'
err = request_irq(riscv_pmu->irq, riscv_pmu->handle_irq,
^~
/freedom-u-sdk/linux/arch/riscv/kernel/perf_event.c:355:7: error:
'IRQF_PER_CPU' undeclared (first use in this function); did you mean
'IRQD_PER_CPU'?
IRQF_PER_CPU, "riscv-base-perf", NULL);
^~~~~~~~~~~~
IRQD_PER_CPU
/freedom-u-sdk/linux/arch/riscv/kernel/perf_event.c:355:7: note: each
undeclared identifier is reported only once for each function it
appears in
/freedom-u-sdk/linux/arch/riscv/kernel/perf_event.c: In function
'release_pmc_hardware':
/freedom-u-sdk/linux/arch/riscv/kernel/perf_event.c:365:15: error:
'const struct riscv_pmu' has no member named 'irq'
if (riscv_pmu->irq >=0) {
^~
/freedom-u-sdk/linux/arch/riscv/kernel/perf_event.c:366:21: error:
'const struct riscv_pmu' has no member named 'irq'
free_irq(riscv_pmu->irq, NULL);
^~
/freedom-u-sdk/linux/arch/riscv/kernel/perf_event.c: At top level:
/freedom-u-sdk/linux/arch/riscv/kernel/perf_event.c:457:3: error:
'const struct riscv_pmu' has no member named 'irq'
.irq = -1,
^~~
/freedom-u-sdk/linux/arch/riscv/kernel/perf_event.c:457:9: warning:
excess elements in struct initializer
.irq = -1,
^
/freedom-u-sdk/linux/arch/riscv/kernel/perf_event.c:457:9: note: (near
initialization for 'riscv_base_pmu')
/freedom-u-sdk/linux/arch/riscv/kernel/perf_event.c:460:34: error:
array type has incomplete element type 'struct of_device_id'
static const struct of_device_id riscv_pmu_of_ids[] = {
^~~~~~~~~~~~~~~~
/freedom-u-sdk/linux/arch/riscv/kernel/perf_event.c:461:3: error:
field name not in record or union initializer
{.compatible = "riscv,base-pmu", .data = &riscv_base_pmu},
^
/freedom-u-sdk/linux/arch/riscv/kernel/perf_event.c:461:3: note: (near
initialization for 'riscv_pmu_of_ids')
/freedom-u-sdk/linux/arch/riscv/kernel/perf_event.c:461:35: error:
field name not in record or union initializer
{.compatible = "riscv,base-pmu", .data = &riscv_base_pmu},
^
/freedom-u-sdk/linux/arch/riscv/kernel/perf_event.c:461:35: note:
(near initialization for 'riscv_pmu_of_ids')
/freedom-u-sdk/linux/arch/riscv/kernel/perf_event.c: In function
'init_hw_perf_events':
/freedom-u-sdk/linux/arch/riscv/kernel/perf_event.c:468:29: error:
implicit declaration of function 'of_find_node_by_type'; did you mean
'__inc_node_state'? [-Werror=implicit-function-declaration]
struct device_node *node = of_find_node_by_type(NULL, "pmu");
^~~~~~~~~~~~~~~~~~~~
__inc_node_state
/freedom-u-sdk/linux/arch/riscv/kernel/perf_event.c:468:29: warning:
initialization makes pointer from integer without a cast
[-Wint-conversion]
/freedom-u-sdk/linux/arch/riscv/kernel/perf_event.c:470:15: error:
'of_id' undeclared (first use in this function)
if (node && (of_id = of_match_node(riscv_pmu_of_ids, node)))
^~~~~
/freedom-u-sdk/linux/arch/riscv/kernel/perf_event.c:470:23: error:
implicit declaration of function 'of_match_node'; did you mean
'for_each_node'? [-Werror=implicit-function-declaration]
if (node && (of_id = of_match_node(riscv_pmu_of_ids, node)))
^~~~~~~~~~~~~
for_each_node
/freedom-u-sdk/linux/arch/riscv/kernel/perf_event.c:467:14: warning:
unused variable 'pmu' [-Wunused-variable]
struct pmu *pmu;
^~~
At top level:
/freedom-u-sdk/linux/arch/riscv/kernel/perf_event.c:460:34: warning:
'riscv_pmu_of_ids' defined but not used [-Wunused-variable]
static const struct of_device_id riscv_pmu_of_ids[] = {
^~~~~~~~~~~~~~~~
cc1: some warnings being treated as errors
/freedom-u-sdk/linux/scripts/Makefile.build:316: recipe for target
'arch/riscv/kernel/perf_event.o' failed
make[3]: *** [arch/riscv/kernel/perf_event.o] Error 1
/freedom-u-sdk/linux/Makefile:1018: recipe for target 'arch/riscv/kernel' failed
On Tue, Apr 17, 2018 at 1:38 AM, Alan Kao <alankao@andestech.com> wrote:
> This patch provide a basic PMU, riscv_base_pmu, which supports two
> general hardware event, instructions and cycles. Furthermore, this
> PMU serves as a reference implementation to ease the portings in
> the future.
>
> riscv_base_pmu should be able to run on any RISC-V machine that
> conforms to the Priv-Spec. Note that the latest qemu model hasn't
> fully support a proper behavior of Priv-Spec 1.10 yet, but work
> around should be easy with very small fixes. Please check
> https://github.com/riscv/riscv-qemu/pull/115 for future updates.
>
> Cc: Nick Hu <nickhu@andestech.com>
> Cc: Greentime Hu <greentime@andestech.com>
> Signed-off-by: Alan Kao <alankao@andestech.com>
> ---
> arch/riscv/Kconfig | 13 +
> arch/riscv/include/asm/perf_event.h | 78 ++++-
> arch/riscv/kernel/Makefile | 1 +
> arch/riscv/kernel/perf_event.c | 478 ++++++++++++++++++++++++++++
> 4 files changed, 566 insertions(+), 4 deletions(-)
> create mode 100644 arch/riscv/kernel/perf_event.c
>
> diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
> index c22ebe08e902..90d9c8e50377 100644
> --- a/arch/riscv/Kconfig
> +++ b/arch/riscv/Kconfig
> @@ -203,6 +203,19 @@ config RISCV_ISA_C
> config RISCV_ISA_A
> def_bool y
>
> +menu "supported PMU type"
> + depends on PERF_EVENTS
> +
> +config RISCV_BASE_PMU
> + bool "Base Performance Monitoring Unit"
> + def_bool y
> + help
> + A base PMU that serves as a reference implementation and has limited
> + feature of perf. It can run on any RISC-V machines so serves as the
> + fallback, but this option can also be disable to reduce kernel size.
> +
> +endmenu
> +
> endmenu
>
> menu "Kernel type"
> diff --git a/arch/riscv/include/asm/perf_event.h b/arch/riscv/include/asm/perf_event.h
> index e13d2ff29e83..eb6bb1c46387 100644
> --- a/arch/riscv/include/asm/perf_event.h
> +++ b/arch/riscv/include/asm/perf_event.h
> @@ -1,13 +1,83 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> /*
> * Copyright (C) 2018 SiFive
> + * Copyright (C) 2018 Andes Technology Corporation
> *
> - * This program is free software; you can redistribute it and/or
> - * modify it under the terms of the GNU General Public Licence
> - * as published by the Free Software Foundation; either version
> - * 2 of the Licence, or (at your option) any later version.
> */
>
> #ifndef _ASM_RISCV_PERF_EVENT_H
> #define _ASM_RISCV_PERF_EVENT_H
>
> +#include <linux/perf_event.h>
> +#include <linux/ptrace.h>
> +
> +#define RISCV_BASE_COUNTERS 2
> +
> +/*
> + * The RISCV_MAX_COUNTERS parameter should be specified.
> + */
> +
> +#ifdef CONFIG_RISCV_BASE_PMU
> +#define RISCV_MAX_COUNTERS 2
> +#endif
> +
> +#ifndef RISCV_MAX_COUNTERS
> +#error "Please provide a valid RISCV_MAX_COUNTERS for the PMU."
> +#endif
> +
> +/*
> + * These are the indexes of bits in counteren register *minus* 1,
> + * except for cycle. It would be coherent if it can directly mapped
> + * to counteren bit definition, but there is a *time* register at
> + * counteren[1]. Per-cpu structure is scarce resource here.
> + *
> + * According to the spec, an implementation can support counter up to
> + * mhpmcounter31, but many high-end processors has at most 6 general
> + * PMCs, we give the definition to MHPMCOUNTER8 here.
> + */
> +#define RISCV_PMU_CYCLE 0
> +#define RISCV_PMU_INSTRET 1
> +#define RISCV_PMU_MHPMCOUNTER3 2
> +#define RISCV_PMU_MHPMCOUNTER4 3
> +#define RISCV_PMU_MHPMCOUNTER5 4
> +#define RISCV_PMU_MHPMCOUNTER6 5
> +#define RISCV_PMU_MHPMCOUNTER7 6
> +#define RISCV_PMU_MHPMCOUNTER8 7
> +
> +#define RISCV_OP_UNSUPP (-EOPNOTSUPP)
> +
> +struct cpu_hw_events {
> + /* # currently enabled events*/
> + int n_events;
> + /* currently enabled events */
> + struct perf_event *events[RISCV_MAX_COUNTERS];
> + /* vendor-defined PMU data */
> + void *platform;
> +};
> +
> +struct riscv_pmu {
> + struct pmu *pmu;
> +
> + /* generic hw/cache events table */
> + const int *hw_events;
> + const int (*cache_events)[PERF_COUNT_HW_CACHE_MAX]
> + [PERF_COUNT_HW_CACHE_OP_MAX]
> + [PERF_COUNT_HW_CACHE_RESULT_MAX];
> + /* method used to map hw/cache events */
> + int (*map_hw_event)(u64 config);
> + int (*map_cache_event)(u64 config);
> +
> + /* max generic hw events in map */
> + int max_events;
> + /* number total counters, 2(base) + x(general) */
> + int num_counters;
> + /* the width of the counter */
> + int counter_width;
> +
> + /* vendor-defined PMU features */
> + void *platform;
> +
> + irqreturn_t (*handle_irq)(int irq_num, void *dev);
> +};
> +
> #endif /* _ASM_RISCV_PERF_EVENT_H */
> diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
> index ffa439d4a364..f50d19816757 100644
> --- a/arch/riscv/kernel/Makefile
> +++ b/arch/riscv/kernel/Makefile
> @@ -39,5 +39,6 @@ obj-$(CONFIG_MODULE_SECTIONS) += module-sections.o
> obj-$(CONFIG_FUNCTION_TRACER) += mcount.o
> obj-$(CONFIG_DYNAMIC_FTRACE) += mcount-dyn.o
> obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
> +obj-$(CONFIG_PERF_EVENTS) += perf_event.o
>
> clean:
> diff --git a/arch/riscv/kernel/perf_event.c b/arch/riscv/kernel/perf_event.c
> new file mode 100644
> index 000000000000..afeda9831720
> --- /dev/null
> +++ b/arch/riscv/kernel/perf_event.c
> @@ -0,0 +1,478 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (C) 2008 Thomas Gleixner <tglx@linutronix.de>
> + * Copyright (C) 2008-2009 Red Hat, Inc., Ingo Molnar
> + * Copyright (C) 2009 Jaswinder Singh Rajput
> + * Copyright (C) 2009 Advanced Micro Devices, Inc., Robert Richter
> + * Copyright (C) 2008-2009 Red Hat, Inc., Peter Zijlstra
> + * Copyright (C) 2009 Intel Corporation, <markus.t.metzger@intel.com>
> + * Copyright (C) 2009 Google, Inc., Stephane Eranian
> + * Copyright 2014 Tilera Corporation. All Rights Reserved.
> + * Copyright (C) 2018 Andes Technology Corporation
> + *
> + * Perf_events support for RISC-V platforms.
> + *
> + * Since the spec. (as of now, Priv-Spec 1.10) does not provide enough
> + * functionality for perf event to fully work, this file provides
> + * the very basic framework only.
> + *
> + * For platform portings, please check Documentations/riscv/pmu.txt.
> + *
> + * The Copyright line includes x86 and tile ones.
> + */
> +
> +#include <linux/kprobes.h>
> +#include <linux/kernel.h>
> +#include <linux/kdebug.h>
> +#include <linux/mutex.h>
> +#include <linux/bitmap.h>
> +#include <linux/irq.h>
> +#include <linux/interrupt.h>
> +#include <linux/perf_event.h>
> +#include <linux/atomic.h>
> +#include <asm/perf_event.h>
> +
> +static const struct riscv_pmu *riscv_pmu __read_mostly;
> +static DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events);
> +
> +/*
> + * Hardware & cache maps and their methods
> + */
> +
> +static const int riscv_hw_event_map[] = {
> + [PERF_COUNT_HW_CPU_CYCLES] = RISCV_PMU_CYCLE,
> + [PERF_COUNT_HW_INSTRUCTIONS] = RISCV_PMU_INSTRET,
> + [PERF_COUNT_HW_CACHE_REFERENCES] = RISCV_OP_UNSUPP,
> + [PERF_COUNT_HW_CACHE_MISSES] = RISCV_OP_UNSUPP,
> + [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = RISCV_OP_UNSUPP,
> + [PERF_COUNT_HW_BRANCH_MISSES] = RISCV_OP_UNSUPP,
> + [PERF_COUNT_HW_BUS_CYCLES] = RISCV_OP_UNSUPP,
> +};
> +
> +#define C(x) PERF_COUNT_HW_CACHE_##x
> +static const int riscv_cache_event_map[PERF_COUNT_HW_CACHE_MAX]
> +[PERF_COUNT_HW_CACHE_OP_MAX]
> +[PERF_COUNT_HW_CACHE_RESULT_MAX] = {
> + [C(L1D)] = {
> + [C(OP_READ)] = {
> + [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
> + [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
> + },
> + [C(OP_WRITE)] = {
> + [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
> + [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
> + },
> + [C(OP_PREFETCH)] = {
> + [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
> + [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
> + },
> + },
> + [C(L1I)] = {
> + [C(OP_READ)] = {
> + [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
> + [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
> + },
> + [C(OP_WRITE)] = {
> + [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
> + [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
> + },
> + [C(OP_PREFETCH)] = {
> + [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
> + [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
> + },
> + },
> + [C(LL)] = {
> + [C(OP_READ)] = {
> + [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
> + [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
> + },
> + [C(OP_WRITE)] = {
> + [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
> + [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
> + },
> + [C(OP_PREFETCH)] = {
> + [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
> + [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
> + },
> + },
> + [C(DTLB)] = {
> + [C(OP_READ)] = {
> + [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
> + [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
> + },
> + [C(OP_WRITE)] = {
> + [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
> + [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
> + },
> + [C(OP_PREFETCH)] = {
> + [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
> + [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
> + },
> + },
> + [C(ITLB)] = {
> + [C(OP_READ)] = {
> + [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
> + [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
> + },
> + [C(OP_WRITE)] = {
> + [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
> + [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
> + },
> + [C(OP_PREFETCH)] = {
> + [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
> + [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
> + },
> + },
> + [C(BPU)] = {
> + [C(OP_READ)] = {
> + [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
> + [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
> + },
> + [C(OP_WRITE)] = {
> + [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
> + [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
> + },
> + [C(OP_PREFETCH)] = {
> + [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
> + [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
> + },
> + },
> +};
> +
> +static int riscv_map_hw_event(u64 config)
> +{
> + if (config >= riscv_pmu->max_events)
> + return -EINVAL;
> +
> + return riscv_pmu->hw_events[config];
> +}
> +
> +int riscv_map_cache_decode(u64 config, unsigned int *type,
> + unsigned int *op, unsigned int *result)
> +{
> + return -ENOENT;
> +}
> +
> +static int riscv_map_cache_event(u64 config)
> +{
> + unsigned int type, op, result;
> + int err = -ENOENT;
> + int code;
> +
> + err = riscv_map_cache_decode(config, &type, &op, &result);
> + if (!riscv_pmu->cache_events || err)
> + return err;
> +
> + if (type >= PERF_COUNT_HW_CACHE_MAX ||
> + op >= PERF_COUNT_HW_CACHE_OP_MAX ||
> + result >= PERF_COUNT_HW_CACHE_RESULT_MAX)
> + return -EINVAL;
> +
> + code = (*riscv_pmu->cache_events)[type][op][result];
> + if (code == RISCV_OP_UNSUPP)
> + return -EINVAL;
> +
> + return code;
> +}
> +
> +/*
> + * Low-level functions: reading/writing counters
> + */
> +
> +static inline u64 read_counter(int idx)
> +{
> + u64 val = 0;
> +
> + switch (idx) {
> + case RISCV_PMU_CYCLE:
> + val = csr_read(cycle);
> + break;
> + case RISCV_PMU_INSTRET:
> + val = csr_read(instret);
> + break;
> + default:
> + WARN_ON_ONCE(idx < 0 || idx > RISCV_MAX_COUNTERS);
> + return -EINVAL;
> + }
> +
> + return val;
> +}
> +
> +static inline void write_counter(int idx, u64 value)
> +{
> + /* currently not supported */
> +}
> +
> +/*
> + * pmu->read: read and update the counter
> + *
> + * Other architectures' implementation often have a xxx_perf_event_update
> + * routine, which can return counter values when called in the IRQ, but
> + * return void when being called by the pmu->read method.
> + */
> +static void riscv_pmu_read(struct perf_event *event)
> +{
> + struct hw_perf_event *hwc = &event->hw;
> + u64 prev_raw_count, new_raw_count;
> + u64 oldval;
> + int idx = hwc->idx;
> + u64 delta;
> +
> + do {
> + prev_raw_count = local64_read(&hwc->prev_count);
> + new_raw_count = read_counter(idx);
> +
> + oldval = local64_cmpxchg(&hwc->prev_count, prev_raw_count,
> + new_raw_count);
> + } while (oldval != prev_raw_count);
> +
> + /*
> + * delta is the value to update the counter we maintain in the kernel.
> + */
> + delta = (new_raw_count - prev_raw_count) &
> + ((1ULL << riscv_pmu->counter_width) - 1);
> + local64_add(delta, &event->count);
> + /*
> + * Something like local64_sub(delta, &hwc->period_left) here is
> + * needed if there is an interrupt for perf.
> + */
> +}
> +
> +/*
> + * State transition functions:
> + *
> + * stop()/start() & add()/del()
> + */
> +
> +/*
> + * pmu->stop: stop the counter
> + */
> +static void riscv_pmu_stop(struct perf_event *event, int flags)
> +{
> + struct hw_perf_event *hwc = &event->hw;
> +
> + WARN_ON_ONCE(hwc->state & PERF_HES_STOPPED);
> + hwc->state |= PERF_HES_STOPPED;
> +
> + if ((flags & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) {
> + riscv_pmu->read(event);
> + hwc->state |= PERF_HES_UPTODATE;
> + }
> +}
> +
> +/*
> + * pmu->start: start the event.
> + */
> +static void riscv_pmu_start(struct perf_event *event, int flags)
> +{
> + struct hw_perf_event *hwc = &event->hw;
> +
> + if (WARN_ON_ONCE(!(event->hw.state & PERF_HES_STOPPED)))
> + return;
> +
> + if (flags & PERF_EF_RELOAD) {
> + WARN_ON_ONCE(!(event->hw.state & PERF_HES_UPTODATE));
> +
> + /*
> + * Set the counter to the period to the next interrupt here,
> + * if you have any.
> + */
> + }
> +
> + hwc->state = 0;
> + perf_event_update_userpage(event);
> +
> + /*
> + * Since we cannot write to counters, this serves as an initialization
> + * to the delta-mechanism in pmu->read(); otherwise, the delta would be
> + * wrong when pmu->read is called for the first time.
> + */
> + local64_set(&hwc->prev_count, read_counter(hwc->idx));
> +}
> +
> +/*
> + * pmu->add: add the event to PMU.
> + */
> +static int riscv_pmu_add(struct perf_event *event, int flags)
> +{
> + struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
> + struct hw_perf_event *hwc = &event->hw;
> +
> + if (cpuc->n_events == riscv_pmu->num_counters)
> + return -ENOSPC;
> +
> + /*
> + * We don't have general conunters, so no binding-event-to-counter
> + * process here.
> + *
> + * Indexing using hwc->config generally not works, since config may
> + * contain extra information, but here the only info we have in
> + * hwc->config is the event index.
> + */
> + hwc->idx = hwc->config;
> + cpuc->events[hwc->idx] = event;
> + cpuc->n_events++;
> +
> + hwc->state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
> +
> + if (flags & PERF_EF_START)
> + riscv_pmu->start(event, PERF_EF_RELOAD);
> +
> + return 0;
> +}
> +
> +/*
> + * pmu->del: delete the event from PMU.
> + */
> +static void riscv_pmu_del(struct perf_event *event, int flags)
> +{
> + struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
> + struct hw_perf_event *hwc = &event->hw;
> +
> + cpuc->events[hwc->idx] = NULL;
> + cpuc->n_events--;
> + riscv_pmu->stop(event, PERF_EF_UPDATE);
> + perf_event_update_userpage(event);
> +}
> +
> +/*
> + * Interrupt: a skeletion for reference.
> + */
> +
> +static DEFINE_MUTEX(pmc_reserve_mutex);
> +
> +irqreturn_t riscv_base_pmu_handle_irq(int irq_num, void *dev);
> +{
> +}
> +
> +static int reserve_pmc_hardware(void)
> +{
> + int err = 0;
> +
> + mutex_lock(&pmc_reserve_mutex);
> + if (riscv_pmu->irq >=0 && riscv_pmu->handle_irq) {
> + err = request_irq(riscv_pmu->irq, riscv_pmu->handle_irq,
> + IRQF_PER_CPU, "riscv-base-perf", NULL);
> + }
> + mutex_unlock(&pmc_reserve_mutex);
> +
> + return err;
> +}
> +
> +void release_pmc_hardware(void)
> +{
> + mutex_lock(&pmc_reserve_mutex);
> + if (riscv_pmu->irq >=0) {
> + free_irq(riscv_pmu->irq, NULL);
> + }
> + mutex_unlock(&pmc_reserve_mutex);
> +}
> +
> +/*
> + * Event Initialization/Finalization
> + */
> +
> +static atomic_t riscv_active_events = ATOMIC_INIT(0);
> +
> +static void riscv_event_destroy(struct perf_event *event)
> +{
> + if (atomic_dec_return(&riscv_active_events) == 0)
> + release_pmc_hardware();
> +}
> +
> +static int riscv_event_init(struct perf_event *event)
> +{
> + struct perf_event_attr *attr = &event->attr;
> + struct hw_perf_event *hwc = &event->hw;
> + int err;
> + int code;
> +
> + if (atomic_inc_return(&riscv_active_events) == 1)
> + err = reserve_pmc_hardware();
> +
> + if (err) {
> + pr_warn("PMC hardware not available\n");
> + atomic_dec(&riscv_active_events);
> + return -EBUSY;
> + }
> +
> + switch (event->attr.type) {
> + case PERF_TYPE_HARDWARE:
> + code = riscv_pmu->map_hw_event(attr->config);
> + break;
> + case PERF_TYPE_HW_CACHE:
> + code = riscv_pmu->map_cache_event(attr->config);
> + break;
> + case PERF_TYPE_RAW:
> + return -EOPNOTSUPP;
> + default:
> + return -ENOENT;
> + }
> +
> + event->destroy = riscv_event_destroy;
> + if (code < 0) {
> + event->destroy(event);
> + return code;
> + }
> +
> + /*
> + * idx is set to -1 because the index of a general event should not be
> + * decided until binding to some counter in pmu->add().
> + *
> + * But since we don't have such support, later in pmu->add(), we just
> + * use hwc->config as the index instead.
> + */
> + hwc->config = code;
> + hwc->idx = -1;
> +
> + return 0;
> +}
> +
> +/*
> + * Initialization
> + */
> +
> +static struct pmu min_pmu = {
> + .name = "riscv-base",
> + .event_init = riscv_event_init,
> + .add = riscv_pmu_add,
> + .del = riscv_pmu_del,
> + .start = riscv_pmu_start,
> + .stop = riscv_pmu_stop,
> + .read = riscv_pmu_read,
> +};
> +
> +static const struct riscv_pmu riscv_base_pmu = {
> + .pmu = &min_pmu,
> + .max_events = ARRAY_SIZE(riscv_hw_event_map),
> + .map_hw_event = riscv_map_hw_event,
> + .hw_events = riscv_hw_event_map,
> + .map_cache_event = riscv_map_cache_event,
> + .cache_events = &riscv_cache_event_map,
> + .counter_width = 63,
> + .num_counters = RISCV_BASE_COUNTERS + 0,
> + .handle_irq = &riscv_base_pmu_handle_irq,
> +
> + /* This means this PMU has no IRQ. */
> + .irq = -1,
> +};
> +
> +static const struct of_device_id riscv_pmu_of_ids[] = {
> + {.compatible = "riscv,base-pmu", .data = &riscv_base_pmu},
> + { /* sentinel value */ }
> +};
> +
> +int __init init_hw_perf_events(void)
> +{
> + struct pmu *pmu;
> + struct device_node *node = of_find_node_by_type(NULL, "pmu");
> +
> + if (node && (of_id = of_match_node(riscv_pmu_of_ids, node)))
> + riscv_pmu = of_id->data;
> + else
> + riscv_pmu = &riscv_base_pmu;
> +
> + perf_pmu_register(riscv_pmu->pmu, "cpu", PERF_TYPE_RAW);
> + return 0;
> +}
> +arch_initcall(init_hw_perf_events);
> --
> 2.17.0
>
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH] Documentation/i2c: sync docs with current state of i2c-tools.
From: Sam Hansen @ 2018-04-17 19:17 UTC (permalink / raw)
To: Wolfram Sang
Cc: Jean Delvare, linux-i2c, Jonathan Corbet, linux-doc, linux-kernel
In-Reply-To: <20180414062718.3tbsdb6jhjurpfta@katana>
On Fri, Apr 13, 2018 at 11:27 PM, Wolfram Sang <wsa@the-dreams.de> wrote:
>
>> (also, did I send the v3 patch series threaded correctly?)
>
> Yes, that worked. Thanks!
>
> Things to improve there: I was both in To: and CC: field, so I got mails
> twice. Jean was missing completely.
Ah, thanks. I had been using scripts/get_maintainer.pl to determine
the CC list, I'll make sure the right people are on the cc line in the
future.
>
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v3 06/10] drivers/peci: Add a PECI adapter driver for Aspeed AST24xx/AST25xx
From: Jae Hyun Yoo @ 2018-04-17 18:21 UTC (permalink / raw)
To: Robin Murphy, Alan Cox, Andrew Jeffery, Andrew Lunn,
Andy Shevchenko, Arnd Bergmann, Benjamin Herrenschmidt,
Fengguang Wu, Greg KH, Guenter Roeck, Haiyue Wang, James Feist,
Jason M Biils, Jean Delvare, Joel Stanley, Julia Cartwright,
Miguel Ojeda, Milton Miller II, Pavel Machek, Randy Dunlap,
Stef van Os, Sumeet R Pawnikar, Vernon Mauery
Cc: linux-hwmon, devicetree, linux-doc, openbmc, linux-kernel,
linux-arm-kernel
In-Reply-To: <93e7f93c-a2e4-1e16-be4c-b908f88b9897@arm.com>
Hi Robin,
On 4/17/2018 6:37 AM, Robin Murphy wrote:
> Just a drive-by nit:
>
> On 10/04/18 19:32, Jae Hyun Yoo wrote:
> [...]
>> +#define PECI_CTRL_SAMPLING_MASK GENMASK(19, 16)
>> +#define PECI_CTRL_SAMPLING(x) (((x) << 16) &
>> PECI_CTRL_SAMPLING_MASK)
>> +#define PECI_CTRL_SAMPLING_GET(x) (((x) & PECI_CTRL_SAMPLING_MASK)
>> >> 16)
>
> FWIW, <linux/bitfield.h> already provides functionality like this, so it
> might be worth taking a look at FIELD_{GET,PREP}() to save all these
> local definitions.
>
> Robin.
Yes, that looks better. Thanks a lot for your pointing it out.
Jae
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v3 04/10] Documentations: dt-bindings: Add a document of PECI adapter driver for Aspeed AST24xx/25xx SoCs
From: Jae Hyun Yoo @ 2018-04-17 18:16 UTC (permalink / raw)
To: Rob Herring
Cc: Alan Cox, Andrew Jeffery, Andrew Lunn, Andy Shevchenko,
Arnd Bergmann, Benjamin Herrenschmidt, Fengguang Wu, Greg KH,
Guenter Roeck, Haiyue Wang, James Feist, Jason M Biils,
Jean Delvare, Joel Stanley, Julia Cartwright, Miguel Ojeda,
Milton Miller II, Pavel Machek, Randy Dunlap, Stef van Os,
Sumeet R Pawnikar, Vernon Mauery, linux-kernel@vger.kernel.org,
linux-doc, devicetree, Linux HWMON List,
moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
OpenBMC Maillist
In-Reply-To: <CAL_Jsq+1wC-KhXPeCSNhCeCih6=CatJbyumO51ucD17Rt7qofw@mail.gmail.com>
On 4/17/2018 6:16 AM, Rob Herring wrote:
> On Mon, Apr 16, 2018 at 6:12 PM, Jae Hyun Yoo
> <jae.hyun.yoo@linux.intel.com> wrote:
>> On 4/16/2018 11:10 AM, Rob Herring wrote:
>>>
>>> On Tue, Apr 10, 2018 at 11:32:06AM -0700, Jae Hyun Yoo wrote:
>>>>
>>>> This commit adds a dt-bindings document of PECI adapter driver for Aspeed
>>>> AST24xx/25xx SoCs.
>
> [...]
>
>>>> +- clocks : Should contain clock source for PECI controller.
>>>> + Should reference clkin.
>>>> +- clock_frequency : Should contain the operation frequency of PECI
>>>> controller
>>>> + in units of Hz.
>>>> + 187500 ~ 24000000
>>>
>>>
>>> This is the frequency of the bus or used to derive it? It would be
>>> better to specify the bus frequency instead and have the driver
>>> calculate its internal freq. And then use "bus-frequency" instead.
>>>
>>
>> I agree with you. Actually, it is being used for operation frequency setting
>> of PECI controller module in SoC so it's different from the meaning of
>> "bus-frequency". I'll change it to "operation-frequency".
>
> No, now you've gone from a standard property name to something custom.
> Why do you need to set the frequency in DT if it is not related to the
> interface frequency?
>
> Rob
>
Actually, the interface frequency is affected by the operation frequency
but there is no description of its relationship in datasheet. I'll check
again about the detail to ASPEED chip vendor and will use
'bus-frequency' if available.
Thanks,
Jae
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH bpf-next v3 7/8] bpf: add documentation for eBPF helpers (51-57)
From: Andrey Ignatov @ 2018-04-17 17:55 UTC (permalink / raw)
To: Quentin Monnet
Cc: daniel, ast, netdev, oss-drivers, linux-doc, linux-man,
Lawrence Brakmo, Yonghong Song, Josef Bacik
In-Reply-To: <20180417143438.7018-8-quentin.monnet@netronome.com>
Quentin Monnet <quentin.monnet@netronome.com> [Tue, 2018-04-17 07:36 -0700]:
> Add documentation for eBPF helper functions to bpf.h user header file.
> This documentation can be parsed with the Python script provided in
> another commit of the patch series, in order to provide a RST document
> that can later be converted into a man page.
>
> The objective is to make the documentation easily understandable and
> accessible to all eBPF developers, including beginners.
>
> This patch contains descriptions for the following helper functions:
>
> Helpers from Lawrence:
> - bpf_setsockopt()
> - bpf_getsockopt()
> - bpf_sock_ops_cb_flags_set()
>
> Helpers from Yonghong:
> - bpf_perf_event_read_value()
> - bpf_perf_prog_read_value()
>
> Helper from Josef:
> - bpf_override_return()
>
> Helper from Andrey:
> - bpf_bind()
>
> v3:
> - bpf_perf_event_read_value(): Fix time of selection for perf event type
> in description. Remove occurences of "cores" to avoid confusion with
> "CPU".
> - bpf_bind(): Remove last paragraph of description, which was off topic.
>
> Cc: Lawrence Brakmo <brakmo@fb.com>
> Cc: Yonghong Song <yhs@fb.com>
> Cc: Josef Bacik <jbacik@fb.com>
> Cc: Andrey Ignatov <rdna@fb.com>
> Signed-off-by: Quentin Monnet <quentin.monnet@netronome.com>
>
> fix patch 7: Yonghong and Andrey
> ---
> include/uapi/linux/bpf.h | 178 +++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 178 insertions(+)
>
> diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> index dd79a1c82adf..350459c583de 100644
> --- a/include/uapi/linux/bpf.h
> +++ b/include/uapi/linux/bpf.h
> + *
> + * int bpf_bind(struct bpf_sock_addr_kern *ctx, struct sockaddr *addr, int addr_len)
> + * Description
> + * Bind the socket associated to *ctx* to the address pointed by
> + * *addr*, of length *addr_len*. This allows for making outgoing
> + * connection from the desired IP address, which can be useful for
> + * example when all processes inside a cgroup should use one
> + * single IP address on a host that has multiple IP configured.
> + *
> + * This helper works for IPv4 and IPv6, TCP and UDP sockets. The
> + * domain (*addr*\ **->sa_family**) must be **AF_INET** (or
> + * **AF_INET6**). Looking for a free port to bind to can be
> + * expensive, therefore binding to port is not permitted by the
> + * helper: *addr*\ **->sin_port** (or **sin6_port**, respectively)
> + * must be set to zero.
> + * Return
> + * 0 on success, or a negative error in case of failure.
Acked-by: Andrey Ignatov <rdna@fb.com>
for bpf_bind() helper.
--
Andrey Ignatov
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH bpf-next v3 7/8] bpf: add documentation for eBPF helpers (51-57)
From: Yonghong Song @ 2018-04-17 17:51 UTC (permalink / raw)
To: Quentin Monnet, daniel, ast
Cc: netdev, oss-drivers, linux-doc, linux-man, Lawrence Brakmo,
Josef Bacik, Andrey Ignatov
In-Reply-To: <20180417143438.7018-8-quentin.monnet@netronome.com>
On 4/17/18 7:34 AM, Quentin Monnet wrote:
> Add documentation for eBPF helper functions to bpf.h user header file.
> This documentation can be parsed with the Python script provided in
> another commit of the patch series, in order to provide a RST document
> that can later be converted into a man page.
>
> The objective is to make the documentation easily understandable and
> accessible to all eBPF developers, including beginners.
>
> This patch contains descriptions for the following helper functions:
>
> Helpers from Lawrence:
> - bpf_setsockopt()
> - bpf_getsockopt()
> - bpf_sock_ops_cb_flags_set()
>
> Helpers from Yonghong:
> - bpf_perf_event_read_value()
> - bpf_perf_prog_read_value()
>
> Helper from Josef:
> - bpf_override_return()
>
> Helper from Andrey:
> - bpf_bind()
>
> v3:
> - bpf_perf_event_read_value(): Fix time of selection for perf event type
> in description. Remove occurences of "cores" to avoid confusion with
> "CPU".
> - bpf_bind(): Remove last paragraph of description, which was off topic.
>
> Cc: Lawrence Brakmo <brakmo@fb.com>
> Cc: Yonghong Song <yhs@fb.com>
> Cc: Josef Bacik <jbacik@fb.com>
> Cc: Andrey Ignatov <rdna@fb.com>
> Signed-off-by: Quentin Monnet <quentin.monnet@netronome.com>
>
> fix patch 7: Yonghong and Andrey
> ---
> include/uapi/linux/bpf.h | 178 +++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 178 insertions(+)
>
> diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> index dd79a1c82adf..350459c583de 100644
> --- a/include/uapi/linux/bpf.h
> +++ b/include/uapi/linux/bpf.h
> @@ -1234,6 +1234,28 @@ union bpf_attr {
> * Return
> * 0
> *
> + * int bpf_setsockopt(struct bpf_sock_ops_kern *bpf_socket, int level, int optname, char *optval, int optlen)
> + * Description
> + * Emulate a call to **setsockopt()** on the socket associated to
> + * *bpf_socket*, which must be a full socket. The *level* at
> + * which the option resides and the name *optname* of the option
> + * must be specified, see **setsockopt(2)** for more information.
> + * The option value of length *optlen* is pointed by *optval*.
> + *
> + * This helper actually implements a subset of **setsockopt()**.
> + * It supports the following *level*\ s:
> + *
> + * * **SOL_SOCKET**, which supports the following *optname*\ s:
> + * **SO_RCVBUF**, **SO_SNDBUF**, **SO_MAX_PACING_RATE**,
> + * **SO_PRIORITY**, **SO_RCVLOWAT**, **SO_MARK**.
> + * * **IPPROTO_TCP**, which supports the following *optname*\ s:
> + * **TCP_CONGESTION**, **TCP_BPF_IW**,
> + * **TCP_BPF_SNDCWND_CLAMP**.
> + * * **IPPROTO_IP**, which supports *optname* **IP_TOS**.
> + * * **IPPROTO_IPV6**, which supports *optname* **IPV6_TCLASS**.
> + * Return
> + * 0 on success, or a negative error in case of failure.
> + *
> * int bpf_skb_adjust_room(struct sk_buff *skb, u32 len_diff, u32 mode, u64 flags)
> * Description
> * Grow or shrink the room for data in the packet associated to
> @@ -1281,6 +1303,162 @@ union bpf_attr {
> * performed again.
> * Return
> * 0 on success, or a negative error in case of failure.
> + *
> + * int bpf_perf_event_read_value(struct bpf_map *map, u64 flags, struct bpf_perf_event_value *buf, u32 buf_size)
> + * Description
> + * Read the value of a perf event counter, and store it into *buf*
> + * of size *buf_size*. This helper relies on a *map* of type
> + * **BPF_MAP_TYPE_PERF_EVENT_ARRAY**. The nature of the perf event
> + * counter is selected when *map* is updated with perf event file
> + * descriptors. The *map* is an array whose size is the number of
> + * available CPUs, and each cell contains a value relative to one
> + * CPU. The value to retrieve is indicated by *flags*, that
> + * contains the index of the CPU to look up, masked with
> + * **BPF_F_INDEX_MASK**. Alternatively, *flags* can be set to
> + * **BPF_F_CURRENT_CPU** to indicate that the value for the
> + * current CPU should be retrieved.
> + *
> + * This helper behaves in a way close to
> + * **bpf_perf_event_read**\ () helper, save that instead of
> + * just returning the value observed, it fills the *buf*
> + * structure. This allows for additional data to be retrieved: in
> + * particular, the enabled and running times (in *buf*\
> + * **->enabled** and *buf*\ **->running**, respectively) are
> + * copied.
> + *
> + * These values are interesting, because hardware PMU (Performance
> + * Monitoring Unit) counters are limited resources. When there are
> + * more PMU based perf events opened than available counters,
> + * kernel will multiplex these events so each event gets certain
> + * percentage (but not all) of the PMU time. In case that
> + * multiplexing happens, the number of samples or counter value
> + * will not reflect the case compared to when no multiplexing
> + * occurs. This makes comparison between different runs difficult.
> + * Typically, the counter value should be normalized before
> + * comparing to other experiments. The usual normalization is done
> + * as follows.
> + *
> + * ::
> + *
> + * normalized_counter = counter * t_enabled / t_running
> + *
> + * Where t_enabled is the time enabled for event and t_running is
> + * the time running for event since last normalization. The
> + * enabled and running times are accumulated since the perf event
> + * open. To achieve scaling factor between two invocations of an
> + * eBPF program, users can can use CPU id as the key (which is
> + * typical for perf array usage model) to remember the previous
> + * value and do the calculation inside the eBPF program.
> + * Return
> + * 0 on success, or a negative error in case of failure.
> + *
> + * int bpf_perf_prog_read_value(struct bpf_perf_event_data_kern *ctx, struct bpf_perf_event_value *buf, u32 buf_size)
> + * Description
> + * For en eBPF program attached to a perf event, retrieve the
> + * value of the event counter associated to *ctx* and store it in
> + * the structure pointed by *buf* and of size *buf_size*. Enabled
> + * and running times are also stored in the structure (see
> + * description of helper **bpf_perf_event_read_value**\ () for
> + * more details).
> + * Return
> + * 0 on success, or a negative error in case of failure.
Acked-by: Yonghong Song <yhs@fb.com>
for the following two helpers:
- bpf_perf_event_read_value()
- bpf_perf_prog_read_value()
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [RFC 06/10] misc: pci_endpoint_test: Add MSI-X support
From: Gustavo Pimentel @ 2018-04-17 17:38 UTC (permalink / raw)
To: Kishon Vijay Abraham I, bhelgaas@google.com,
lorenzo.pieralisi@arm.com, Joao.Pinto@synopsys.com,
jingoohan1@gmail.com, adouglas@cadence.com,
niklas.cassel@axis.com, jesper.nilsson@axis.com
Cc: linux-pci@vger.kernel.org, linux-doc@vger.kernel.org,
linux-kernel@vger.kernel.org
In-Reply-To: <b25dcfb1-e770-e302-d9aa-7c35f6c58fa5@ti.com>
Hi Kishon,
On 17/04/2018 11:33, Kishon Vijay Abraham I wrote:
> Hi,
>
> On Tuesday 10 April 2018 10:44 PM, Gustavo Pimentel wrote:
>> Adds the MSI-X support and updates driver documentation accordingly.
>>
>> Changes the driver parameter in order to allow the interruption type
>> selection.
>>
>> Signed-off-by: Gustavo Pimentel <gustavo.pimentel@synopsys.com>
>> ---
>> Documentation/misc-devices/pci-endpoint-test.txt | 3 +
>> drivers/misc/pci_endpoint_test.c | 102 +++++++++++++++++------
>> 2 files changed, 79 insertions(+), 26 deletions(-)
>>
>> diff --git a/Documentation/misc-devices/pci-endpoint-test.txt b/Documentation/misc-devices/pci-endpoint-test.txt
>> index 4ebc359..fdfa0f6 100644
>> --- a/Documentation/misc-devices/pci-endpoint-test.txt
>> +++ b/Documentation/misc-devices/pci-endpoint-test.txt
>> @@ -10,6 +10,7 @@ The PCI driver for the test device performs the following tests
>> *) verifying addresses programmed in BAR
>> *) raise legacy IRQ
>> *) raise MSI IRQ
>> + *) raise MSI-X IRQ
>> *) read data
>> *) write data
>> *) copy data
>> @@ -25,6 +26,8 @@ ioctl
>> PCITEST_LEGACY_IRQ: Tests legacy IRQ
>> PCITEST_MSI: Tests message signalled interrupts. The MSI number
>> to be tested should be passed as argument.
>> + PCITEST_MSIX: Tests message signalled interrupts. The MSI-X number
>> + to be tested should be passed as argument.
>> PCITEST_WRITE: Perform write tests. The size of the buffer should be passed
>> as argument.
>> PCITEST_READ: Perform read tests. The size of the buffer should be passed
>> diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c
>> index 37db0fc..a7d9354 100644
>> --- a/drivers/misc/pci_endpoint_test.c
>> +++ b/drivers/misc/pci_endpoint_test.c
>> @@ -42,11 +42,16 @@
>> #define PCI_ENDPOINT_TEST_COMMAND 0x4
>> #define COMMAND_RAISE_LEGACY_IRQ BIT(0)
>> #define COMMAND_RAISE_MSI_IRQ BIT(1)
>> -#define MSI_NUMBER_SHIFT 2
>> -/* 6 bits for MSI number */
>> -#define COMMAND_READ BIT(8)
>> -#define COMMAND_WRITE BIT(9)
>> -#define COMMAND_COPY BIT(10)
>> +#define COMMAND_RAISE_MSIX_IRQ BIT(2)
>> +#define IRQ_TYPE_SHIFT 3
>> +#define IRQ_TYPE_LEGACY 0
>> +#define IRQ_TYPE_MSI 1
>> +#define IRQ_TYPE_MSIX 2
>> +#define MSI_NUMBER_SHIFT 5
>
> Now that you are anyways fixing this, add a new register entry for MSI numbers.
> Let's not keep COMMAND and MSI's together.
What you suggest?
>> +/* 12 bits for MSI number */
>> +#define COMMAND_READ BIT(17)
>> +#define COMMAND_WRITE BIT(18)
>> +#define COMMAND_COPY BIT(19)
>
> This change should be done along with the pci-epf-test in a single patch.
To be clear, you're saying is this patch should be just be squashed into the
patch number 8 [1], because there is a lot of dependencies namely the defines,
that is used on the alter functions.
[1] -> https://patchwork.ozlabs.org/patch/896841/
>>
>> #define PCI_ENDPOINT_TEST_STATUS 0x8
>> #define STATUS_READ_SUCCESS BIT(0)
>> @@ -73,9 +78,9 @@ static DEFINE_IDA(pci_endpoint_test_ida);
>> #define to_endpoint_test(priv) container_of((priv), struct pci_endpoint_test, \
>> miscdev)
>>
>> -static bool no_msi;
>> -module_param(no_msi, bool, 0444);
>> -MODULE_PARM_DESC(no_msi, "Disable MSI interrupt in pci_endpoint_test");
>
> Let's not remove this just to make sure existing users doesn't get affected.
Hum, by making an internal conversion? Like this
no_msi = false <=> irq_type = 1
no_msi = true <=> irq_type = 0
>> +static int irq_type = IRQ_TYPE_MSIX;
>> +module_param(irq_type, int, 0444);
>> +MODULE_PARM_DESC(irq_type, "IRQ mode selection in pci_endpoint_test (0 - Legacy, 1 - MSI, 2 - MSI-X)");
>>
>> enum pci_barno {
>> BAR_0,
>> @@ -103,7 +108,7 @@ struct pci_endpoint_test {
>> struct pci_endpoint_test_data {
>> enum pci_barno test_reg_bar;
>> size_t alignment;
>> - bool no_msi;
>> + int irq_type;
>> };
>>
>> static inline u32 pci_endpoint_test_readl(struct pci_endpoint_test *test,
>> @@ -177,10 +182,10 @@ static bool pci_endpoint_test_bar(struct pci_endpoint_test *test,
>>
>> static bool pci_endpoint_test_legacy_irq(struct pci_endpoint_test *test)
>> {
>> - u32 val;
>> + u32 val = COMMAND_RAISE_LEGACY_IRQ;
>>
>> - pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND,
>> - COMMAND_RAISE_LEGACY_IRQ);
>> + val |= (IRQ_TYPE_LEGACY << IRQ_TYPE_SHIFT);
>> + pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND, val);
>> val = wait_for_completion_timeout(&test->irq_raised,
>> msecs_to_jiffies(1000));
>> if (!val)
>> @@ -192,12 +197,12 @@ static bool pci_endpoint_test_legacy_irq(struct pci_endpoint_test *test)
>> static bool pci_endpoint_test_msi_irq(struct pci_endpoint_test *test,
>> u8 msi_num)
>> {
>> - u32 val;
>> + u32 val = COMMAND_RAISE_MSI_IRQ;
>> struct pci_dev *pdev = test->pdev;
>>
>> - pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND,
>> - msi_num << MSI_NUMBER_SHIFT |
>> - COMMAND_RAISE_MSI_IRQ);
>> + val |= (msi_num << MSI_NUMBER_SHIFT);
>> + val |= (IRQ_TYPE_MSI << IRQ_TYPE_SHIFT);
>> + pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND, val);
>> val = wait_for_completion_timeout(&test->irq_raised,
>> msecs_to_jiffies(1000));
>> if (!val)
>> @@ -209,6 +214,26 @@ static bool pci_endpoint_test_msi_irq(struct pci_endpoint_test *test,
>> return false;
>> }
>>
>> +static bool pci_endpoint_test_msix_irq(struct pci_endpoint_test *test,
>> + u16 msix_num)
>> +{
>> + u32 val = COMMAND_RAISE_MSIX_IRQ;
>> + struct pci_dev *pdev = test->pdev;
>> +
>> + val |= (msix_num << MSI_NUMBER_SHIFT);
>> + val |= (IRQ_TYPE_MSIX << IRQ_TYPE_SHIFT);
>> + pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND, val);
>> + val = wait_for_completion_timeout(&test->irq_raised,
>> + msecs_to_jiffies(1000));
>> + if (!val)
>> + return false;
>> +
>> + if (test->last_irq - pdev->irq == msix_num - 1)
>> + return true;
>> +
>> + return false;
>
> I think you can have a single function for msix_irq and msi_irq.
Ok.
>
> Thanks
> Kishon
>
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v2 2/3] coresight: Add section for integration with the perf tools
From: Randy Dunlap @ 2018-04-17 17:26 UTC (permalink / raw)
To: Mathieu Poirier, linux-arm-kernel, corbet
Cc: linux-doc, linux-kernel, Ben.Gainey
In-Reply-To: <1523981287-15370-3-git-send-email-mathieu.poirier@linaro.org>
On 04/17/18 09:08, Mathieu Poirier wrote:
> Adding a section that document how to use the Coresight framework and
> drivers from the perf tools.
>
> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
Acked-by: Randy Dunlap <rdunlap@infradead.org>
Thanks.
> ---
> Documentation/trace/coresight.txt | 52 ++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 51 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/trace/coresight.txt b/Documentation/trace/coresight.txt
> index 710c75b6c73f..ab0d0f2d5cec 100644
> --- a/Documentation/trace/coresight.txt
> +++ b/Documentation/trace/coresight.txt
> @@ -187,10 +187,19 @@ that can be performed on them (see "struct coresight_ops"). The
> specific to that component only. "Implementation defined" customisations are
> expected to be accessed and controlled using those entries.
>
> +
> How to use the tracer modules
> -----------------------------
>
> -Before trace collection can start, a coresight sink needs to be identify.
> +There are two ways to use the Coresight framework: 1) using the perf cmd line
> +tools and 2) interacting directly with the Coresight devices using the sysFS
> +interface. Preference is given to the former as using the sysFS interface
> +requires a deep understanding of the Coresight HW. The following sections
> +provide details on using both methods.
> +
> +1) Using the sysFS interface:
> +
> +Before trace collection can start, a coresight sink needs to be identified.
> There is no limit on the amount of sinks (nor sources) that can be enabled at
> any given moment. As a generic operation, all device pertaining to the sink
> class will have an "active" entry in sysfs:
> @@ -295,6 +304,47 @@ Instruction 13570831 0x8026B584 E28DD00C false ADD
> Instruction 0 0x8026B588 E8BD8000 true LDM sp!,{pc}
> Timestamp Timestamp: 17107041535
>
> +2) Using perf framework:
> +
> +Coresight tracers are represented using the Perf framework's Performance
> +Monitoring Unit (PMU) abstraction. As such the perf framework takes charge of
> +controlling when tracing gets enabled based on when the process of interest is
> +scheduled. When configured in a system, Coresight PMUs will be listed when
> +queried by the perf command line tool:
> +
> + linaro@linaro-nano:~$ ./perf list pmu
> +
> + List of pre-defined events (to be used in -e):
> +
> + cs_etm// [Kernel PMU event]
> +
> + linaro@linaro-nano:~$
> +
> +Regardless of the number of tracers available in a system (usually equal to the
> +amount of processor cores), the "cs_etm" PMU will be listed only once.
> +
> +A Coresight PMU works the same way as any other PMU, i.e the name of the PMU is
> +listed along with configuration options within forward slashes '/'. Since a
> +Coresight system will typically have more than one sink, the name of the sink to
> +work with needs to be specified as an event option. Names for sink to choose
> +from are listed in sysFS under ($SYSFS)/bus/coresight/devices:
> +
> + root@linaro-nano:~# ls /sys/bus/coresight/devices/
> + 20010000.etf 20040000.funnel 20100000.stm 22040000.etm
> + 22140000.etm 230c0000.funnel 23240000.etm 20030000.tpiu
> + 20070000.etr 20120000.replicator 220c0000.funnel
> + 23040000.etm 23140000.etm 23340000.etm
> +
> + root@linaro-nano:~# perf record -e cs_etm/@20070000.etr/u --per-thread program
> +
> +The syntax within the forward slashes '/' is important. The '@' character
> +tells the parser that a sink is about to be specified and that this is the sink
> +to use for the trace session.
> +
> +More information on the above and other example on how to use Coresight with
> +the perf tools can be found in the "HOWTO.md" file of the openCSD gitHub
> +repository [3].
> +
> How to use the STM module
> -------------------------
>
>
--
~Randy
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH v2 2/3] coresight: Add section for integration with the perf tools
From: Mathieu Poirier @ 2018-04-17 16:08 UTC (permalink / raw)
To: linux-arm-kernel, corbet; +Cc: linux-doc, linux-kernel, rdunlap, Ben.Gainey
In-Reply-To: <1523981287-15370-1-git-send-email-mathieu.poirier@linaro.org>
Adding a section that document how to use the Coresight framework and
drivers from the perf tools.
Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
---
Documentation/trace/coresight.txt | 52 ++++++++++++++++++++++++++++++++++++++-
1 file changed, 51 insertions(+), 1 deletion(-)
diff --git a/Documentation/trace/coresight.txt b/Documentation/trace/coresight.txt
index 710c75b6c73f..ab0d0f2d5cec 100644
--- a/Documentation/trace/coresight.txt
+++ b/Documentation/trace/coresight.txt
@@ -187,10 +187,19 @@ that can be performed on them (see "struct coresight_ops"). The
specific to that component only. "Implementation defined" customisations are
expected to be accessed and controlled using those entries.
+
How to use the tracer modules
-----------------------------
-Before trace collection can start, a coresight sink needs to be identify.
+There are two ways to use the Coresight framework: 1) using the perf cmd line
+tools and 2) interacting directly with the Coresight devices using the sysFS
+interface. Preference is given to the former as using the sysFS interface
+requires a deep understanding of the Coresight HW. The following sections
+provide details on using both methods.
+
+1) Using the sysFS interface:
+
+Before trace collection can start, a coresight sink needs to be identified.
There is no limit on the amount of sinks (nor sources) that can be enabled at
any given moment. As a generic operation, all device pertaining to the sink
class will have an "active" entry in sysfs:
@@ -295,6 +304,47 @@ Instruction 13570831 0x8026B584 E28DD00C false ADD
Instruction 0 0x8026B588 E8BD8000 true LDM sp!,{pc}
Timestamp Timestamp: 17107041535
+2) Using perf framework:
+
+Coresight tracers are represented using the Perf framework's Performance
+Monitoring Unit (PMU) abstraction. As such the perf framework takes charge of
+controlling when tracing gets enabled based on when the process of interest is
+scheduled. When configured in a system, Coresight PMUs will be listed when
+queried by the perf command line tool:
+
+ linaro@linaro-nano:~$ ./perf list pmu
+
+ List of pre-defined events (to be used in -e):
+
+ cs_etm// [Kernel PMU event]
+
+ linaro@linaro-nano:~$
+
+Regardless of the number of tracers available in a system (usually equal to the
+amount of processor cores), the "cs_etm" PMU will be listed only once.
+
+A Coresight PMU works the same way as any other PMU, i.e the name of the PMU is
+listed along with configuration options within forward slashes '/'. Since a
+Coresight system will typically have more than one sink, the name of the sink to
+work with needs to be specified as an event option. Names for sink to choose
+from are listed in sysFS under ($SYSFS)/bus/coresight/devices:
+
+ root@linaro-nano:~# ls /sys/bus/coresight/devices/
+ 20010000.etf 20040000.funnel 20100000.stm 22040000.etm
+ 22140000.etm 230c0000.funnel 23240000.etm 20030000.tpiu
+ 20070000.etr 20120000.replicator 220c0000.funnel
+ 23040000.etm 23140000.etm 23340000.etm
+
+ root@linaro-nano:~# perf record -e cs_etm/@20070000.etr/u --per-thread program
+
+The syntax within the forward slashes '/' is important. The '@' character
+tells the parser that a sink is about to be specified and that this is the sink
+to use for the trace session.
+
+More information on the above and other example on how to use Coresight with
+the perf tools can be found in the "HOWTO.md" file of the openCSD gitHub
+repository [3].
+
How to use the STM module
-------------------------
--
2.7.4
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH v2 1/3] coresight: Remove obsolete reference to "owner" in CoreSight descriptor
From: Mathieu Poirier @ 2018-04-17 16:08 UTC (permalink / raw)
To: linux-arm-kernel, corbet; +Cc: linux-doc, linux-kernel, rdunlap, Ben.Gainey
In-Reply-To: <1523981287-15370-1-git-send-email-mathieu.poirier@linaro.org>
Field "owner" of struct coresight_desc has been removed a while back but
the documentation was not updated to reflect the changes.
Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
---
Documentation/trace/coresight.txt | 3 ---
1 file changed, 3 deletions(-)
diff --git a/Documentation/trace/coresight.txt b/Documentation/trace/coresight.txt
index 6f0120c3a4f1..710c75b6c73f 100644
--- a/Documentation/trace/coresight.txt
+++ b/Documentation/trace/coresight.txt
@@ -187,9 +187,6 @@ that can be performed on them (see "struct coresight_ops"). The
specific to that component only. "Implementation defined" customisations are
expected to be accessed and controlled using those entries.
-Last but not least, "struct module *owner" is expected to be set to reflect
-the information carried in "THIS_MODULE".
-
How to use the tracer modules
-----------------------------
--
2.7.4
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox