From f4c0b0aa58d9b7e30ab0a95e33da84d53b3d764a Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Mon, 20 Feb 2017 15:33:50 +0200 Subject: perf/core: Keep AUX flags in the output handle In preparation for adding more flags to perf AUX records, introduce a separate API for setting the flags for a session, rather than appending more bool arguments to perf_aux_output_end. This allows to set each flag at the time a corresponding condition is detected, instead of tracking it in each driver's private state. Signed-off-by: Will Deacon Signed-off-by: Alexander Shishkin Signed-off-by: Peter Zijlstra (Intel) Cc: Arnaldo Carvalho de Melo Cc: Arnaldo Carvalho de Melo Cc: Jiri Olsa Cc: Linus Torvalds Cc: Mathieu Poirier Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Thomas Gleixner Cc: Vince Weaver Cc: vince@deater.net Link: http://lkml.kernel.org/r/20170220133352.17995-3-alexander.shishkin@linux.intel.com Signed-off-by: Ingo Molnar --- drivers/hwtracing/coresight/coresight-etb10.c | 9 ++++----- drivers/hwtracing/coresight/coresight-etm-perf.c | 9 ++++----- drivers/hwtracing/coresight/coresight-priv.h | 2 -- drivers/hwtracing/coresight/coresight-tmc-etf.c | 7 +++---- 4 files changed, 11 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c index d7325c6534ad..979ea6ec7902 100644 --- a/drivers/hwtracing/coresight/coresight-etb10.c +++ b/drivers/hwtracing/coresight/coresight-etb10.c @@ -321,7 +321,7 @@ static int etb_set_buffer(struct coresight_device *csdev, static unsigned long etb_reset_buffer(struct coresight_device *csdev, struct perf_output_handle *handle, - void *sink_config, bool *lost) + void *sink_config) { unsigned long size = 0; struct cs_buffers *buf = sink_config; @@ -343,7 +343,6 @@ static unsigned long etb_reset_buffer(struct coresight_device *csdev, * resetting parameters here and squaring off with the ring * buffer API in the tracer PMU is fine. */ - *lost = !!local_xchg(&buf->lost, 0); size = local_xchg(&buf->data_size, 0); } @@ -385,7 +384,7 @@ static void etb_update_buffer(struct coresight_device *csdev, (unsigned long)write_ptr); write_ptr &= ~(ETB_FRAME_SIZE_WORDS - 1); - local_inc(&buf->lost); + perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED); } /* @@ -396,7 +395,7 @@ static void etb_update_buffer(struct coresight_device *csdev, */ status = readl_relaxed(drvdata->base + ETB_STATUS_REG); if (status & ETB_STATUS_RAM_FULL) { - local_inc(&buf->lost); + perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED); to_read = capacity; read_ptr = write_ptr; } else { @@ -429,7 +428,7 @@ static void etb_update_buffer(struct coresight_device *csdev, if (read_ptr > (drvdata->buffer_depth - 1)) read_ptr -= drvdata->buffer_depth; /* let the decoder know we've skipped ahead */ - local_inc(&buf->lost); + perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED); } /* finally tell HW where we want to start reading from */ diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c index 26cfac3e6de7..288a423c1b27 100644 --- a/drivers/hwtracing/coresight/coresight-etm-perf.c +++ b/drivers/hwtracing/coresight/coresight-etm-perf.c @@ -302,7 +302,8 @@ out: return; fail_end_stop: - perf_aux_output_end(handle, 0, true); + perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED); + perf_aux_output_end(handle, 0); fail: event->hw.state = PERF_HES_STOPPED; goto out; @@ -310,7 +311,6 @@ fail: static void etm_event_stop(struct perf_event *event, int mode) { - bool lost; int cpu = smp_processor_id(); unsigned long size; struct coresight_device *sink, *csdev = per_cpu(csdev_src, cpu); @@ -348,10 +348,9 @@ static void etm_event_stop(struct perf_event *event, int mode) return; size = sink_ops(sink)->reset_buffer(sink, handle, - event_data->snk_config, - &lost); + event_data->snk_config); - perf_aux_output_end(handle, size, lost); + perf_aux_output_end(handle, size); } /* Disabling the path make its elements available to other sessions */ diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h index ef9d8e93e3b2..5f662d82052c 100644 --- a/drivers/hwtracing/coresight/coresight-priv.h +++ b/drivers/hwtracing/coresight/coresight-priv.h @@ -76,7 +76,6 @@ enum cs_mode { * @nr_pages: max number of pages granted to us * @offset: offset within the current buffer * @data_size: how much we collected in this run - * @lost: other than zero if we had a HW buffer wrap around * @snapshot: is this run in snapshot mode * @data_pages: a handle the ring buffer */ @@ -85,7 +84,6 @@ struct cs_buffers { unsigned int nr_pages; unsigned long offset; local_t data_size; - local_t lost; bool snapshot; void **data_pages; }; diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c index 1549436e2492..aec61a6d5c63 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etf.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c @@ -329,7 +329,7 @@ static int tmc_set_etf_buffer(struct coresight_device *csdev, static unsigned long tmc_reset_etf_buffer(struct coresight_device *csdev, struct perf_output_handle *handle, - void *sink_config, bool *lost) + void *sink_config) { long size = 0; struct cs_buffers *buf = sink_config; @@ -350,7 +350,6 @@ static unsigned long tmc_reset_etf_buffer(struct coresight_device *csdev, * resetting parameters here and squaring off with the ring * buffer API in the tracer PMU is fine. */ - *lost = !!local_xchg(&buf->lost, 0); size = local_xchg(&buf->data_size, 0); } @@ -389,7 +388,7 @@ static void tmc_update_etf_buffer(struct coresight_device *csdev, */ status = readl_relaxed(drvdata->base + TMC_STS); if (status & TMC_STS_FULL) { - local_inc(&buf->lost); + perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED); to_read = drvdata->size; } else { to_read = CIRC_CNT(write_ptr, read_ptr, drvdata->size); @@ -434,7 +433,7 @@ static void tmc_update_etf_buffer(struct coresight_device *csdev, read_ptr -= drvdata->size; /* Tell the HW */ writel_relaxed(read_ptr, drvdata->base + TMC_RRP); - local_inc(&buf->lost); + perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED); } cur = buf->cur; -- cgit v1.2.3 From 0a6d80c70b9150d6a9cf466d41955e374c2c9fab Mon Sep 17 00:00:00 2001 From: Suravee Suthikulpanit Date: Fri, 24 Feb 2017 02:48:16 -0600 Subject: drivers/iommu/amd: Clean up iommu_pc_get_set_reg() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Clean up coding style and fix a bug in the 64-bit register read logic since it overwrites the upper 32-bit when reading the lower 32-bit. Signed-off-by: Suravee Suthikulpanit Signed-off-by: Borislav Petkov Signed-off-by: Peter Zijlstra (Intel) Cc: Alexander Shishkin Cc: Arnaldo Carvalho de Melo Cc: Jiri Olsa Cc: Jörg Rödel Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Thomas Gleixner Cc: Vince Weaver Cc: iommu@lists.linux-foundation.org Link: http://lkml.kernel.org/r/1487926102-13073-5-git-send-email-Suravee.Suthikulpanit@amd.com Signed-off-by: Ingo Molnar --- drivers/iommu/amd_iommu_init.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index 6130278c5d71..ce65a47e2d0b 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c @@ -2763,22 +2763,25 @@ static int iommu_pc_get_set_reg_val(struct amd_iommu *iommu, if (WARN_ON((fxn > 0x28) || (fxn & 7))) return -ENODEV; - offset = (u32)(((0x40|bank) << 12) | (cntr << 8) | fxn); + offset = (u32)(((0x40 | bank) << 12) | (cntr << 8) | fxn); /* Limit the offset to the hw defined mmio region aperture */ - max_offset_lim = (u32)(((0x40|iommu->max_banks) << 12) | + max_offset_lim = (u32)(((0x40 | iommu->max_banks) << 12) | (iommu->max_counters << 8) | 0x28); if ((offset < MMIO_CNTR_REG_OFFSET) || (offset > max_offset_lim)) return -EINVAL; if (is_write) { - writel((u32)*value, iommu->mmio_base + offset); - writel((*value >> 32), iommu->mmio_base + offset + 4); + u64 val = *value & GENMASK_ULL(47, 0); + + writel((u32)val, iommu->mmio_base + offset); + writel((val >> 32), iommu->mmio_base + offset + 4); } else { *value = readl(iommu->mmio_base + offset + 4); *value <<= 32; - *value = readl(iommu->mmio_base + offset); + *value |= readl(iommu->mmio_base + offset); + *value &= GENMASK_ULL(47, 0); } return 0; -- cgit v1.2.3 From 6b9376e30f42b902260371245f009bc05eb3fdfb Mon Sep 17 00:00:00 2001 From: Suravee Suthikulpanit Date: Fri, 24 Feb 2017 02:48:17 -0600 Subject: x86/events, drivers/iommu/amd: Introduce amd_iommu_get_num_iommus() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce amd_iommu_get_num_iommus(), which returns the value of amd_iommus_present. The function is used to replace direct access to the variable, which is now declared as static. This function will also be used by AMD IOMMU perf driver. Signed-off-by: Suravee Suthikulpanit Signed-off-by: Borislav Petkov Signed-off-by: Peter Zijlstra (Intel) Cc: Alexander Shishkin Cc: Arnaldo Carvalho de Melo Cc: Jiri Olsa Cc: Jörg Rödel Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Thomas Gleixner Cc: Vince Weaver Cc: iommu@lists.linux-foundation.org Link: http://lkml.kernel.org/r/1487926102-13073-6-git-send-email-Suravee.Suthikulpanit@amd.com Signed-off-by: Ingo Molnar --- arch/x86/events/amd/iommu.h | 2 ++ drivers/iommu/amd_iommu.c | 6 +++--- drivers/iommu/amd_iommu_init.c | 11 +++++++++-- drivers/iommu/amd_iommu_proto.h | 1 + drivers/iommu/amd_iommu_types.h | 3 --- 5 files changed, 15 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/arch/x86/events/amd/iommu.h b/arch/x86/events/amd/iommu.h index 845d173278e3..5c5c9329e571 100644 --- a/arch/x86/events/amd/iommu.h +++ b/arch/x86/events/amd/iommu.h @@ -28,6 +28,8 @@ #define IOMMU_BASE_DEVID 0x0000 /* amd_iommu_init.c external support functions */ +extern int amd_iommu_get_num_iommus(void); + extern bool amd_iommu_pc_supported(void); extern u8 amd_iommu_pc_get_max_banks(u16 devid); diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index b17536d6e69b..63cacf5d6cf2 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -1234,7 +1234,7 @@ static void __domain_flush_pages(struct protection_domain *domain, build_inv_iommu_pages(&cmd, address, size, domain->id, pde); - for (i = 0; i < amd_iommus_present; ++i) { + for (i = 0; i < amd_iommu_get_num_iommus(); ++i) { if (!domain->dev_iommu[i]) continue; @@ -1278,7 +1278,7 @@ static void domain_flush_complete(struct protection_domain *domain) { int i; - for (i = 0; i < amd_iommus_present; ++i) { + for (i = 0; i < amd_iommu_get_num_iommus(); ++i) { if (domain && !domain->dev_iommu[i]) continue; @@ -3363,7 +3363,7 @@ static int __flush_pasid(struct protection_domain *domain, int pasid, * IOMMU TLB needs to be flushed before Device TLB to * prevent device TLB refill from IOMMU TLB */ - for (i = 0; i < amd_iommus_present; ++i) { + for (i = 0; i < amd_iommu_get_num_iommus(); ++i) { if (domain->dev_iommu[i] == 0) continue; diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index ce65a47e2d0b..d3ec9c32c446 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c @@ -167,7 +167,9 @@ LIST_HEAD(amd_iommu_list); /* list of all AMD IOMMUs in the /* Array to assign indices to IOMMUs*/ struct amd_iommu *amd_iommus[MAX_IOMMUS]; -int amd_iommus_present; + +/* Number of IOMMUs present in the system */ +static int amd_iommus_present; /* IOMMUs have a non-present cache? */ bool amd_iommu_np_cache __read_mostly; @@ -272,6 +274,11 @@ static inline unsigned long tbl_size(int entry_size) return 1UL << shift; } +int amd_iommu_get_num_iommus(void) +{ + return amd_iommus_present; +} + /* Access to l1 and l2 indexed register spaces */ static u32 iommu_read_l1(struct amd_iommu *iommu, u16 l1, u8 address) @@ -1336,7 +1343,7 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h) /* Add IOMMU to internal data structures */ list_add_tail(&iommu->list, &amd_iommu_list); - iommu->index = amd_iommus_present++; + iommu->index = amd_iommus_present++; if (unlikely(iommu->index >= MAX_IOMMUS)) { WARN(1, "AMD-Vi: System has more IOMMUs than supported by this driver\n"); diff --git a/drivers/iommu/amd_iommu_proto.h b/drivers/iommu/amd_iommu_proto.h index 7eb60c15c582..e8f0710aceb3 100644 --- a/drivers/iommu/amd_iommu_proto.h +++ b/drivers/iommu/amd_iommu_proto.h @@ -21,6 +21,7 @@ #include "amd_iommu_types.h" +extern int amd_iommu_get_num_iommus(void); extern int amd_iommu_init_dma_ops(void); extern int amd_iommu_init_passthrough(void); extern irqreturn_t amd_iommu_int_thread(int irq, void *data); diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h index 003f3ceb2661..4de8f4160bb8 100644 --- a/drivers/iommu/amd_iommu_types.h +++ b/drivers/iommu/amd_iommu_types.h @@ -611,9 +611,6 @@ extern struct list_head amd_iommu_list; */ extern struct amd_iommu *amd_iommus[MAX_IOMMUS]; -/* Number of IOMMUs present in the system */ -extern int amd_iommus_present; - /* * Declarations for the global list of all protection domains */ -- cgit v1.2.3 From f5863a00e73c432b91e4efe1d68778b4ace6a892 Mon Sep 17 00:00:00 2001 From: Suravee Suthikulpanit Date: Fri, 24 Feb 2017 02:48:18 -0600 Subject: x86/events/amd/iommu.c: Modify functions to query max banks and counters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, amd_iommu_pc_get_max_[banks|counters]() use end-point device ID to locate an IOMMU and check the reported max banks/counters. The logic assumes that the IOMMU_BASE_DEVID belongs to the first IOMMU, and uses it to acquire a reference to the first IOMMU, which does not work on certain systems. Instead, modify the function to take an IOMMU index, and use it to query the corresponding AMD IOMMU instance. Currently, hardcode the IOMMU index to 0 since the current AMD IOMMU perf implementation supports only a single IOMMU. A subsequent patch will add support for multiple IOMMUs, and will use a proper IOMMU index. Signed-off-by: Suravee Suthikulpanit Signed-off-by: Borislav Petkov Signed-off-by: Peter Zijlstra (Intel) Cc: Alexander Shishkin Cc: Arnaldo Carvalho de Melo Cc: Jiri Olsa Cc: Jörg Rödel Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Thomas Gleixner Cc: Vince Weaver Cc: iommu@lists.linux-foundation.org Link: http://lkml.kernel.org/r/1487926102-13073-7-git-send-email-Suravee.Suthikulpanit@amd.com Signed-off-by: Ingo Molnar --- arch/x86/events/amd/iommu.c | 17 +++++++---------- arch/x86/events/amd/iommu.h | 9 ++++----- drivers/iommu/amd_iommu_init.c | 34 ++++++++++++++++++++-------------- drivers/iommu/amd_iommu_proto.h | 2 -- 4 files changed, 31 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/arch/x86/events/amd/iommu.c b/arch/x86/events/amd/iommu.c index d4375dadd4e9..10f67d39cac5 100644 --- a/arch/x86/events/amd/iommu.c +++ b/arch/x86/events/amd/iommu.c @@ -239,14 +239,6 @@ static int perf_iommu_event_init(struct perf_event *event) return -EINVAL; } - /* integrate with iommu base devid (0000), assume one iommu */ - perf_iommu->max_banks = - amd_iommu_pc_get_max_banks(IOMMU_BASE_DEVID); - perf_iommu->max_counters = - amd_iommu_pc_get_max_counters(IOMMU_BASE_DEVID); - if ((perf_iommu->max_banks == 0) || (perf_iommu->max_counters == 0)) - return -EINVAL; - /* update the hw_perf_event struct with the iommu config data */ hwc->config = config; hwc->extra_reg.config = config1; @@ -448,6 +440,11 @@ static __init int _init_perf_amd_iommu( return ret; } + perf_iommu->max_banks = amd_iommu_pc_get_max_banks(0); + perf_iommu->max_counters = amd_iommu_pc_get_max_counters(0); + if (!perf_iommu->max_banks || !perf_iommu->max_counters) + return -EINVAL; + perf_iommu->null_group = NULL; perf_iommu->pmu.attr_groups = perf_iommu->attr_groups; @@ -457,8 +454,8 @@ static __init int _init_perf_amd_iommu( amd_iommu_pc_exit(); } else { pr_info("Detected AMD IOMMU (%d banks, %d counters/bank).\n", - amd_iommu_pc_get_max_banks(IOMMU_BASE_DEVID), - amd_iommu_pc_get_max_counters(IOMMU_BASE_DEVID)); + amd_iommu_pc_get_max_banks(0), + amd_iommu_pc_get_max_counters(0)); } return ret; diff --git a/arch/x86/events/amd/iommu.h b/arch/x86/events/amd/iommu.h index 5c5c9329e571..b775107c221e 100644 --- a/arch/x86/events/amd/iommu.h +++ b/arch/x86/events/amd/iommu.h @@ -24,19 +24,18 @@ #define PC_MAX_SPEC_BNKS 64 #define PC_MAX_SPEC_CNTRS 16 -/* iommu pc reg masks*/ -#define IOMMU_BASE_DEVID 0x0000 - /* amd_iommu_init.c external support functions */ extern int amd_iommu_get_num_iommus(void); extern bool amd_iommu_pc_supported(void); -extern u8 amd_iommu_pc_get_max_banks(u16 devid); +extern u8 amd_iommu_pc_get_max_banks(unsigned int idx); -extern u8 amd_iommu_pc_get_max_counters(u16 devid); +extern u8 amd_iommu_pc_get_max_counters(unsigned int idx); extern int amd_iommu_pc_get_set_reg_val(u16 devid, u8 bank, u8 cntr, u8 fxn, u64 *value, bool is_write); +extern struct amd_iommu *get_amd_iommu(int idx); + #endif /*_PERF_EVENT_AMD_IOMMU_H_*/ diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index d3ec9c32c446..8fdf109e6109 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c @@ -2718,6 +2718,18 @@ bool amd_iommu_v2_supported(void) } EXPORT_SYMBOL(amd_iommu_v2_supported); +struct amd_iommu *get_amd_iommu(unsigned int idx) +{ + unsigned int i = 0; + struct amd_iommu *iommu; + + for_each_iommu(iommu) + if (i++ == idx) + return iommu; + return NULL; +} +EXPORT_SYMBOL(get_amd_iommu); + /**************************************************************************** * * IOMMU EFR Performance Counter support functionality. This code allows @@ -2725,17 +2737,14 @@ EXPORT_SYMBOL(amd_iommu_v2_supported); * ****************************************************************************/ -u8 amd_iommu_pc_get_max_banks(u16 devid) +u8 amd_iommu_pc_get_max_banks(unsigned int idx) { - struct amd_iommu *iommu; - u8 ret = 0; + struct amd_iommu *iommu = get_amd_iommu(idx); - /* locate the iommu governing the devid */ - iommu = amd_iommu_rlookup_table[devid]; if (iommu) - ret = iommu->max_banks; + return iommu->max_banks; - return ret; + return 0; } EXPORT_SYMBOL(amd_iommu_pc_get_max_banks); @@ -2745,17 +2754,14 @@ bool amd_iommu_pc_supported(void) } EXPORT_SYMBOL(amd_iommu_pc_supported); -u8 amd_iommu_pc_get_max_counters(u16 devid) +u8 amd_iommu_pc_get_max_counters(unsigned int idx) { - struct amd_iommu *iommu; - u8 ret = 0; + struct amd_iommu *iommu = get_amd_iommu(idx); - /* locate the iommu governing the devid */ - iommu = amd_iommu_rlookup_table[devid]; if (iommu) - ret = iommu->max_counters; + return iommu->max_counters; - return ret; + return 0; } EXPORT_SYMBOL(amd_iommu_pc_get_max_counters); diff --git a/drivers/iommu/amd_iommu_proto.h b/drivers/iommu/amd_iommu_proto.h index e8f0710aceb3..cd2257e20c3f 100644 --- a/drivers/iommu/amd_iommu_proto.h +++ b/drivers/iommu/amd_iommu_proto.h @@ -59,8 +59,6 @@ extern struct iommu_domain *amd_iommu_get_v2_domain(struct pci_dev *pdev); /* IOMMU Performance Counter functions */ extern bool amd_iommu_pc_supported(void); -extern u8 amd_iommu_pc_get_max_banks(u16 devid); -extern u8 amd_iommu_pc_get_max_counters(u16 devid); extern int amd_iommu_pc_get_set_reg_val(u16 devid, u8 bank, u8 cntr, u8 fxn, u64 *value, bool is_write); -- cgit v1.2.3 From 1650dfd1a9bcde8fcfaab776887bb6f4e91830c3 Mon Sep 17 00:00:00 2001 From: Suravee Suthikulpanit Date: Fri, 24 Feb 2017 02:48:19 -0600 Subject: x86/events, drivers/amd/iommu: Prepare for multiple IOMMUs support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, amd_iommu_pc_get_set_reg_val() cannot support multiple IOMMUs. Modify it to allow callers to specify an IOMMU. This is in preparation for supporting multiple IOMMUs. Signed-off-by: Suravee Suthikulpanit Signed-off-by: Borislav Petkov Signed-off-by: Peter Zijlstra (Intel) Cc: Alexander Shishkin Cc: Arnaldo Carvalho de Melo Cc: Jiri Olsa Cc: Jörg Rödel Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Thomas Gleixner Cc: Vince Weaver Cc: iommu@lists.linux-foundation.org Link: http://lkml.kernel.org/r/1487926102-13073-8-git-send-email-Suravee.Suthikulpanit@amd.com Signed-off-by: Ingo Molnar --- arch/x86/events/amd/iommu.c | 38 ++++++++++++++++-------------------- arch/x86/events/amd/iommu.h | 9 +++++++-- drivers/iommu/amd_iommu_init.c | 43 +++++++++++++++++++++++------------------ drivers/iommu/amd_iommu_proto.h | 5 ----- 4 files changed, 48 insertions(+), 47 deletions(-) (limited to 'drivers') diff --git a/arch/x86/events/amd/iommu.c b/arch/x86/events/amd/iommu.c index 10f67d39cac5..88fbc8001460 100644 --- a/arch/x86/events/amd/iommu.c +++ b/arch/x86/events/amd/iommu.c @@ -248,49 +248,45 @@ static int perf_iommu_event_init(struct perf_event *event) static void perf_iommu_enable_event(struct perf_event *ev) { + struct amd_iommu *iommu = get_amd_iommu(0); u8 csource = _GET_CSOURCE(ev); u16 devid = _GET_DEVID(ev); + u8 bank = _GET_BANK(ev); + u8 cntr = _GET_CNTR(ev); u64 reg = 0ULL; reg = csource; - amd_iommu_pc_get_set_reg_val(devid, - _GET_BANK(ev), _GET_CNTR(ev) , - IOMMU_PC_COUNTER_SRC_REG, ®, true); + amd_iommu_pc_set_reg(iommu, bank, cntr, IOMMU_PC_COUNTER_SRC_REG, ®); reg = devid | (_GET_DEVID_MASK(ev) << 32); if (reg) reg |= BIT(31); - amd_iommu_pc_get_set_reg_val(devid, - _GET_BANK(ev), _GET_CNTR(ev) , - IOMMU_PC_DEVID_MATCH_REG, ®, true); + amd_iommu_pc_set_reg(iommu, bank, cntr, IOMMU_PC_DEVID_MATCH_REG, ®); reg = _GET_PASID(ev) | (_GET_PASID_MASK(ev) << 32); if (reg) reg |= BIT(31); - amd_iommu_pc_get_set_reg_val(devid, - _GET_BANK(ev), _GET_CNTR(ev) , - IOMMU_PC_PASID_MATCH_REG, ®, true); + amd_iommu_pc_set_reg(iommu, bank, cntr, IOMMU_PC_PASID_MATCH_REG, ®); reg = _GET_DOMID(ev) | (_GET_DOMID_MASK(ev) << 32); if (reg) reg |= BIT(31); - amd_iommu_pc_get_set_reg_val(devid, - _GET_BANK(ev), _GET_CNTR(ev) , - IOMMU_PC_DOMID_MATCH_REG, ®, true); + amd_iommu_pc_set_reg(iommu, bank, cntr, IOMMU_PC_DOMID_MATCH_REG, ®); } static void perf_iommu_disable_event(struct perf_event *event) { + struct amd_iommu *iommu = get_amd_iommu(0); u64 reg = 0ULL; - amd_iommu_pc_get_set_reg_val(_GET_DEVID(event), - _GET_BANK(event), _GET_CNTR(event), - IOMMU_PC_COUNTER_SRC_REG, ®, true); + amd_iommu_pc_set_reg(iommu, _GET_BANK(event), _GET_CNTR(event), + IOMMU_PC_COUNTER_SRC_REG, ®); } static void perf_iommu_start(struct perf_event *event, int flags) { struct hw_perf_event *hwc = &event->hw; + struct amd_iommu *iommu = get_amd_iommu(0); if (WARN_ON_ONCE(!(hwc->state & PERF_HES_STOPPED))) return; @@ -300,9 +296,8 @@ static void perf_iommu_start(struct perf_event *event, int flags) if (flags & PERF_EF_RELOAD) { u64 prev_raw_count = local64_read(&hwc->prev_count); - amd_iommu_pc_get_set_reg_val(_GET_DEVID(event), - _GET_BANK(event), _GET_CNTR(event), - IOMMU_PC_COUNTER_REG, &prev_raw_count, true); + amd_iommu_pc_set_reg(iommu, _GET_BANK(event), _GET_CNTR(event), + IOMMU_PC_COUNTER_REG, &prev_raw_count); } perf_iommu_enable_event(event); @@ -314,10 +309,11 @@ static void perf_iommu_read(struct perf_event *event) { u64 count, prev, delta; struct hw_perf_event *hwc = &event->hw; + struct amd_iommu *iommu = get_amd_iommu(0); - amd_iommu_pc_get_set_reg_val(_GET_DEVID(event), - _GET_BANK(event), _GET_CNTR(event), - IOMMU_PC_COUNTER_REG, &count, false); + if (amd_iommu_pc_get_reg(iommu, _GET_BANK(event), _GET_CNTR(event), + IOMMU_PC_COUNTER_REG, &count)) + return; /* IOMMU pc counter register is only 48 bits */ count &= GENMASK_ULL(47, 0); diff --git a/arch/x86/events/amd/iommu.h b/arch/x86/events/amd/iommu.h index b775107c221e..62e0702c4374 100644 --- a/arch/x86/events/amd/iommu.h +++ b/arch/x86/events/amd/iommu.h @@ -24,6 +24,8 @@ #define PC_MAX_SPEC_BNKS 64 #define PC_MAX_SPEC_CNTRS 16 +struct amd_iommu; + /* amd_iommu_init.c external support functions */ extern int amd_iommu_get_num_iommus(void); @@ -33,8 +35,11 @@ extern u8 amd_iommu_pc_get_max_banks(unsigned int idx); extern u8 amd_iommu_pc_get_max_counters(unsigned int idx); -extern int amd_iommu_pc_get_set_reg_val(u16 devid, u8 bank, u8 cntr, - u8 fxn, u64 *value, bool is_write); +extern int amd_iommu_pc_set_reg(struct amd_iommu *iommu, u8 bank, u8 cntr, + u8 fxn, u64 *value); + +extern int amd_iommu_pc_get_reg(struct amd_iommu *iommu, u8 bank, u8 cntr, + u8 fxn, u64 *value); extern struct amd_iommu *get_amd_iommu(int idx); diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index 8fdf109e6109..5a11328f4d98 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c @@ -256,10 +256,6 @@ static int amd_iommu_enable_interrupts(void); static int __init iommu_go_to_state(enum iommu_init_state state); static void init_device_table_dma(void); -static int iommu_pc_get_set_reg_val(struct amd_iommu *iommu, - u8 bank, u8 cntr, u8 fxn, - u64 *value, bool is_write); - static inline void update_last_devid(u16 devid) { if (devid > amd_iommu_last_bdf) @@ -1484,6 +1480,8 @@ static int __init init_iommu_all(struct acpi_table_header *table) return 0; } +static int iommu_pc_get_set_reg(struct amd_iommu *iommu, u8 bank, u8 cntr, + u8 fxn, u64 *value, bool is_write); static void init_iommu_perf_ctr(struct amd_iommu *iommu) { @@ -1495,8 +1493,8 @@ static void init_iommu_perf_ctr(struct amd_iommu *iommu) amd_iommu_pc_present = true; /* Check if the performance counters can be written to */ - if ((0 != iommu_pc_get_set_reg_val(iommu, 0, 0, 0, &val, true)) || - (0 != iommu_pc_get_set_reg_val(iommu, 0, 0, 0, &val2, false)) || + if ((iommu_pc_get_set_reg(iommu, 0, 0, 0, &val, true)) || + (iommu_pc_get_set_reg(iommu, 0, 0, 0, &val2, false)) || (val != val2)) { pr_err("AMD-Vi: Unable to write to IOMMU perf counter.\n"); amd_iommu_pc_present = false; @@ -2765,15 +2763,18 @@ u8 amd_iommu_pc_get_max_counters(unsigned int idx) } EXPORT_SYMBOL(amd_iommu_pc_get_max_counters); -static int iommu_pc_get_set_reg_val(struct amd_iommu *iommu, - u8 bank, u8 cntr, u8 fxn, - u64 *value, bool is_write) +static int iommu_pc_get_set_reg(struct amd_iommu *iommu, u8 bank, u8 cntr, + u8 fxn, u64 *value, bool is_write) { u32 offset; u32 max_offset_lim; + /* Make sure the IOMMU PC resource is available */ + if (!amd_iommu_pc_present) + return -ENODEV; + /* Check for valid iommu and pc register indexing */ - if (WARN_ON((fxn > 0x28) || (fxn & 7))) + if (WARN_ON(!iommu || (fxn > 0x28) || (fxn & 7))) return -ENODEV; offset = (u32)(((0x40 | bank) << 12) | (cntr << 8) | fxn); @@ -2799,17 +2800,21 @@ static int iommu_pc_get_set_reg_val(struct amd_iommu *iommu, return 0; } -EXPORT_SYMBOL(amd_iommu_pc_get_set_reg_val); -int amd_iommu_pc_get_set_reg_val(u16 devid, u8 bank, u8 cntr, u8 fxn, - u64 *value, bool is_write) +int amd_iommu_pc_get_reg(struct amd_iommu *iommu, u8 bank, u8 cntr, u8 fxn, u64 *value) { - struct amd_iommu *iommu = amd_iommu_rlookup_table[devid]; + if (!iommu) + return -EINVAL; - /* Make sure the IOMMU PC resource is available */ - if (!amd_iommu_pc_present || iommu == NULL) - return -ENODEV; + return iommu_pc_get_set_reg(iommu, bank, cntr, fxn, value, false); +} +EXPORT_SYMBOL(amd_iommu_pc_get_reg); + +int amd_iommu_pc_set_reg(struct amd_iommu *iommu, u8 bank, u8 cntr, u8 fxn, u64 *value) +{ + if (!iommu) + return -EINVAL; - return iommu_pc_get_set_reg_val(iommu, bank, cntr, fxn, - value, is_write); + return iommu_pc_get_set_reg(iommu, bank, cntr, fxn, value, true); } +EXPORT_SYMBOL(amd_iommu_pc_set_reg); diff --git a/drivers/iommu/amd_iommu_proto.h b/drivers/iommu/amd_iommu_proto.h index cd2257e20c3f..466260f8a1df 100644 --- a/drivers/iommu/amd_iommu_proto.h +++ b/drivers/iommu/amd_iommu_proto.h @@ -57,11 +57,6 @@ extern int amd_iommu_domain_set_gcr3(struct iommu_domain *dom, int pasid, extern int amd_iommu_domain_clear_gcr3(struct iommu_domain *dom, int pasid); extern struct iommu_domain *amd_iommu_get_v2_domain(struct pci_dev *pdev); -/* IOMMU Performance Counter functions */ -extern bool amd_iommu_pc_supported(void); -extern int amd_iommu_pc_get_set_reg_val(u16 devid, u8 bank, u8 cntr, u8 fxn, - u64 *value, bool is_write); - #ifdef CONFIG_IRQ_REMAP extern int amd_iommu_create_irq_domain(struct amd_iommu *iommu); #else -- cgit v1.2.3