From patchwork Mon Dec 3 22:54:52 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mathieu Poirier X-Patchwork-Id: 152785 Delivered-To: patch@linaro.org Received: by 2002:a2e:299d:0:0:0:0:0 with SMTP id p29-v6csp7389012ljp; Mon, 3 Dec 2018 14:55:08 -0800 (PST) X-Google-Smtp-Source: AFSGD/VH8L5AsBCm8qZPYjMY3tBK1yL5BsFc08h+sXHTD2b/V7eO0jmjkWG44OBiWlo2YaHlXqU0 X-Received: by 2002:a63:5722:: with SMTP id l34mr14744277pgb.118.1543877708747; Mon, 03 Dec 2018 14:55:08 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1543877708; cv=none; d=google.com; s=arc-20160816; b=RJhIdg9Kqh9wqmCJpGuedRS1K8rhmbG7VCuk526za7xHUzMkXsziPjxY+x8NQQkxuG ZXRAb/xaj05Vla8oq3rLa51wDKGAHOfPHJXx45HuMITppL/g556GJRLTZvbDOQaD6wth b4tlr0xKfCwVIrTHcqmy7AhOHw9Nc/JhurloJXqndvZQ5v3bWBvXioHrfB9O22euoO1B drSlc9pyhss+Jj6szVDWEfVEGr97lU/i3t54GOXgdHJJMlYeaBzcKpY96+aUcU4zYP4L MNbdSVujRroKlP5ITsyhLCjQPF7aGcZNvood/mN16YODI+m0vBE0tZIE+zmp3jeb4tEK tnsw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature; bh=BBqRtwO6PGFlctrxGALj04LHSsu+aeiHiAedSoB+rfE=; b=nEyAqL75rryrDbbW4LAuIOtxiD2rEl2XFyNOuTnLjBYeI6RET6AiYkVIj8zhS5XdD2 wgopDCvY2TlynGQVxltLKflXb0qgh8x3hqM3vpirs3mf1odBsm9VqIwFSzSgi1GCS07E Kt/ZdOf8JaGs4Ca7PELKyZyPrErQkapk6uUB7Gwk6wQyoei0AOB9fLQqz5LIhc7RLO9H I7rFQtf7YEWCwT82uvq3O8OnXP9M7I4lVvvrY5CL3zVJwKjX57mmmq+vldeQLiWcOeJx 6GYcx4AUIMss5AXzBXFKe+7/lwQhte+S3gxo59Q1fNmYrMbQxuUyOtwd07Q06FYMpKY9 eRzA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=RrOlJSG+; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id e7si13222246pgi.263.2018.12.03.14.55.08; Mon, 03 Dec 2018 14:55:08 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=RrOlJSG+; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726109AbeLCWzH (ORCPT + 32 others); Mon, 3 Dec 2018 17:55:07 -0500 Received: from mail-pf1-f194.google.com ([209.85.210.194]:41581 "EHLO mail-pf1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726065AbeLCWzD (ORCPT ); Mon, 3 Dec 2018 17:55:03 -0500 Received: by mail-pf1-f194.google.com with SMTP id b7so7128494pfi.8 for ; Mon, 03 Dec 2018 14:55:02 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=BBqRtwO6PGFlctrxGALj04LHSsu+aeiHiAedSoB+rfE=; b=RrOlJSG+Y3gW+Hafk4V78OWWfljaTZ5GM8h7jKFhNzSrBGauShndYBsxuAvE5uJLyO 4DyEUr9wBXtcSPvf43JR49GhFDGwG0cvN3+CK3ONl/CwdPAtZJjuIT6zg2bZoVSPDpuv 870pz5JUGRNp4Yo84G2tgEbopj8SYXZGe+XCI= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=BBqRtwO6PGFlctrxGALj04LHSsu+aeiHiAedSoB+rfE=; b=k3GlnJGt5b44/U9qFYM2Yny4KCpyE84Bf6JVZju23FgDZPOlVU9Fmz+5bRS2Ufs0Sc XzDaREY2lGlrj8m4gNK2/24HzHwao2eHGNt2f1WZqTi2keVc927S0CU8/V/IQV/WpNgS u2A6rezNAeyVFsLTKFcvCAnd/lTW5iJcyJd/JInVoMo2LCMMfThXub3R2Lw76lh9o/FN o02BLAoXFCnAk7E1EDIGvMOwrCiT0IXDYomUBeTCoRIILf4lM8ZY95WknfuE2MGcWNIr a8dAmvikKmN20R9oeo/XQ3MGHtp5SR7JaVAiIoIJJDUznhuCNa91uQwPdpqU9Cs/fUub 2mnA== X-Gm-Message-State: AA+aEWaOmF990AzvZqiKEUBv/y3dTcdqxJvDHqdFSHeoWXMJ35UNDinP WB8OxfyTOS9seA3nhvD1lJECQg== X-Received: by 2002:a63:c10f:: with SMTP id w15mr14594722pgf.199.1543877702346; Mon, 03 Dec 2018 14:55:02 -0800 (PST) Received: from xps15.cg.shawcable.net (S0106002369de4dac.cg.shawcable.net. [68.147.8.254]) by smtp.gmail.com with ESMTPSA id v9sm20933057pfg.144.2018.12.03.14.55.00 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 03 Dec 2018 14:55:01 -0800 (PST) From: Mathieu Poirier To: acme@kernel.org, peterz@infradead.org, gregkh@linuxfoundation.org Cc: mingo@redhat.com, tglx@linutronix.de, alexander.shishkin@linux.intel.com, schwidefsky@de.ibm.com, heiko.carstens@de.ibm.com, will.deacon@arm.com, mark.rutland@arm.com, jolsa@redhat.com, namhyung@kernel.org, adrian.hunter@intel.com, ast@kernel.org, hpa@zytor.com, suzuki.poulosi@arm.com, linux-s390@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [PATCH v5 2/6] perf/core: Use ioctl to communicate driver configuration to kernel Date: Mon, 3 Dec 2018 15:54:52 -0700 Message-Id: <1543877696-17174-3-git-send-email-mathieu.poirier@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1543877696-17174-1-git-send-email-mathieu.poirier@linaro.org> References: <1543877696-17174-1-git-send-email-mathieu.poirier@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This patch adds the mechanic needed for user space to send PMU specific configuration to the kernel driver using an ioctl() command. That way events can keep track of options that don't fit in the perf_event_attr structure like the selection of a CoreSight sink to use for the session. Signed-off-by: Mathieu Poirier --- include/linux/perf_event.h | 38 ++++++++++++++++++++++++++ kernel/events/core.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+) -- 2.7.4 diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 53c500f0ca79..8e69b7e309e7 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -114,6 +114,14 @@ struct hw_perf_event_extra { int idx; /* index in shared_regs->regs[] */ }; +/* + * PMU driver configuration + */ +struct pmu_drv_config { + void *config; + raw_spinlock_t lock; +}; + /** * struct hw_perf_event - performance event hardware details: */ @@ -178,6 +186,9 @@ struct hw_perf_event { /* Last sync'ed generation of filters */ unsigned long addr_filters_gen; + /* PMU driver configuration */ + struct pmu_drv_config drv_config; + /* * hw_perf_event::state flags; used to track the PERF_EF_* state. */ @@ -447,6 +458,17 @@ struct pmu { * Filter events for PMU-specific reasons. */ int (*filter_match) (struct perf_event *event); /* optional */ + + /* + * Validate complex PMU configuration that don't fit in the + * perf_event_attr struct. Returns a PMU specific pointer or an error + * value < 0. + * + * As with addr_filters_validate(), runs in the context of the ioctl() + * process and is not serialized with the rest of the PMU callbacks. + */ + void *(*drv_config_validate) (struct perf_event *event, + u64 value); }; enum perf_addr_filter_action_t { @@ -1235,6 +1257,11 @@ static inline bool has_addr_filter(struct perf_event *event) return event->pmu->nr_addr_filters; } +static inline bool has_drv_config(struct perf_event *event) +{ + return event->pmu->drv_config_validate; +} + /* * An inherited event uses parent's filters */ @@ -1249,6 +1276,17 @@ perf_event_addr_filters(struct perf_event *event) return ifh; } +static inline struct pmu_drv_config * +perf_event_get_drv_config(struct perf_event *event) +{ + struct pmu_drv_config *cfg = &event->hw.drv_config; + + if (event->parent) + cfg = &event->parent->hw.drv_config; + + return cfg; +} + extern void perf_event_addr_filters_sync(struct perf_event *event); extern int perf_output_begin(struct perf_output_handle *handle, diff --git a/kernel/events/core.c b/kernel/events/core.c index 84530ab358c3..af7a53c97744 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -5003,6 +5003,8 @@ static inline int perf_fget_light(int fd, struct fd *p) static int perf_event_set_output(struct perf_event *event, struct perf_event *output_event); static int perf_event_set_filter(struct perf_event *event, void __user *arg); +static int perf_event_set_drv_config(struct perf_event *event, + void __user *arg); static int perf_event_set_bpf_prog(struct perf_event *event, u32 prog_fd); static int perf_copy_attr(struct perf_event_attr __user *uattr, struct perf_event_attr *attr); @@ -5089,6 +5091,10 @@ static long _perf_ioctl(struct perf_event *event, unsigned int cmd, unsigned lon return perf_event_modify_attr(event, &new_attr); } + + case PERF_EVENT_IOC_SET_DRV_CONFIG: + return perf_event_set_drv_config(event, (void __user *)arg); + default: return -ENOTTY; } @@ -9128,6 +9134,66 @@ static int perf_event_set_filter(struct perf_event *event, void __user *arg) return ret; } +static void perf_drv_config_replace(struct perf_event *event, void *drv_data) +{ + unsigned long flags; + struct pmu_drv_config *drv_config = &event->hw.drv_config; + + if (!has_drv_config(event)) + return; + + /* Children take their configuration from their parent */ + if (event->parent) + return; + + /* Make sure the PMU doesn't get a handle on the data */ + raw_spin_lock_irqsave(&drv_config->lock, flags); + drv_config->config = drv_data; + raw_spin_unlock_irqrestore(&drv_config->lock, flags); +} + +static int +perf_event_process_drv_config(struct perf_event *event, u64 value) +{ + int ret = -EINVAL; + void *drv_data; + + /* Make sure ctx.mutex is held */ + lockdep_assert_held(&event->ctx->mutex); + + /* Children take their configuration from their parent */ + if (WARN_ON_ONCE(event->parent)) + goto out; + + drv_data = event->pmu->drv_config_validate(event, value); + if (IS_ERR(drv_data)) { + ret = PTR_ERR(drv_data); + goto out; + } + + perf_drv_config_replace(event, drv_data); + + ret = 0; +out: + return ret; +} + +static int perf_event_set_drv_config(struct perf_event *event, void __user *arg) +{ + int ret; + u64 value; + + if (!has_drv_config(event)) + return -EINVAL; + + if (copy_from_user(&value, arg, sizeof(value))) + return -EFAULT; + + ret = perf_event_process_drv_config(event, value); + + return ret; +} + /* * hrtimer based swevent callback */ @@ -10052,6 +10118,7 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu, if (attr->freq && attr->sample_freq) hwc->sample_period = 1; hwc->last_period = hwc->sample_period; + raw_spin_lock_init(&hwc->drv_config.lock); local64_set(&hwc->period_left, hwc->sample_period);