Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933859AbdCVHGg (ORCPT ); Wed, 22 Mar 2017 03:06:36 -0400 Received: from mail-cys01nam02on0048.outbound.protection.outlook.com ([104.47.37.48]:20064 "EHLO NAM02-CY1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1758881AbdCVHEd (ORCPT ); Wed, 22 Mar 2017 03:04:33 -0400 Authentication-Results: vger.kernel.org; dkim=none (message not signed) header.d=none;vger.kernel.org; dmarc=none action=none header.from=amd.com; From: Suravee Suthikulpanit To: , CC: , , , , Suravee Suthikulpanit , Suravee Suthikulpanit Subject: [PATCH v12 10/10] perf/amd/iommu: Enable support for multiple IOMMUs Date: Wed, 22 Mar 2017 02:02:42 -0500 Message-ID: <1490166162-10002-11-git-send-email-Suravee.Suthikulpanit@amd.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1490166162-10002-1-git-send-email-Suravee.Suthikulpanit@amd.com> References: <1490166162-10002-1-git-send-email-Suravee.Suthikulpanit@amd.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [114.109.128.54] X-ClientProxiedBy: SG2PR01CA0012.apcprd01.prod.exchangelabs.com (10.165.9.150) To MWHPR12MB1454.namprd12.prod.outlook.com (10.172.55.135) X-MS-Office365-Filtering-Correlation-Id: b9a5d176-45ed-4e0c-4060-08d470f1a20a X-MS-Office365-Filtering-HT: Tenant X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:(22001)(48565401081);SRVR:MWHPR12MB1454; X-Microsoft-Exchange-Diagnostics: 1;MWHPR12MB1454;3:YvKIXqYLaSsXFPzuQcOI/tMPye+oMdcR2o5GfsWRQ3sFUt3/bMWov90acOiAwSkf8rg6QEMO23/jA9/IUixClTcfH98p6qpdkKmTBltCqnvzpoeIQeeKAXhgGcWRnBzb+E6P0aVld9s97omEAhYja2eozESmB1a+4N22DYgNBomydQxSThwgx6jJqSwmbnkYGU0OBaOo2nYNHF6KBxSJl7cPx7qrNSuFURsoqGKcil0nJ396DQJOGZIsR2OZIxuQV+uO75N01Mm0er4sOTYBXDjHE04uB+6JDQRiH3MsmDY=;25:PY1ZQvGVlmU+WDg73qCRykFnCrejKnBN2AswKlnJr8Ym0slt09XSOLmjBSpc5mJr5h8wPEVQOdq+B0Bn8UT0kViSwJamBm6R+0YGgec1yfU/kHxT6O3QfBwpRMM+iZ86+1ydc5in1mZ+ocE0z+0af2MqRBgxheAvm6lnWjg3rLc6p3py7pSnUi+Mkg2LiWz+IixI6dQD8/MjWOqDMvL2keqK848IFeqrhYD2Y0FW7vEsU2IcpgjOBV1aW2DnM/HhFCuRaTmhdN2tDrWZTBKDEY2bxENcM49SJbovAcOkq8/FLSCq9WTY10SYG63ZuLiTinDW0BpPdv+x9l3o/GO1bxxDHFmerV7JSYRb4AEHld8ge4/JmFbHaqUyk6NdzpaZH18eUHmhihvTrleYMTKXPT+mPlj52iFB4yXeqm2o2lxEo748I6VtTXpyv+jn/fSYrazq/9EJbi3ZXys3nzPUQw== X-Microsoft-Exchange-Diagnostics: 1;MWHPR12MB1454;31:KoTK0CY61JYaxaLmFF8I0C2f9YXdoglnQ7R2xyEGM6NdwOIl1AnRmGW1qI/j1QnrMAG+8r8le2zMVDc8A7atpWQIUNvaIGARGEs29VtHF2kI/ibacwryPYI8mhTyLABP2uNcxTMXK+O66Lu5QTkHrC9WAGgJDz8ov5SziDafowgAHb+UyRzN1+CJOH7/sW2LBJc2Duq+OTpUF2dlTXePu9/JflbfF2rgrLg7VvL6bpHk8zmwqPyqVYlAA8ab/yiu;20:ib/Aza1RgAyLA2toqMU+jAwFQ6qXBJPGNY1qqFdz8OUqXr22N+yuWqSwlU6rL2ub2LqK+Cfh1H+ehW2k1deWhQgw3IlY3S/qEscIh5cv9bq8xmdS4xVV7kNJW2Jufb17WgiZEd2GZh4eh/rs58uYbmY+QvErwjtPaVpKTuEQGtCtyDGYDd4JJG5ravc8468EyoLo75uJz/zMxIG23L1iThr4HAlpO0M0pMyszV5E1RQem2Tbyp0TqSCLrKpbeoLSMK5fIt7H+qA1gLpP7Dqs4BWFGJWN1VL/4HtcjJE1To5SelrA1AlAUQaISGv5CkjO5e6XfQ9Q+kwTIY1ELFYGpXJp5KN0TjMIcGsszfgrRXMKFx0suBL3L1I+dg6zaatL0WBbD0u+7iE2lR5UvJm5N8ThpzdvcD1SdIsShTuDacY9MdG5X/YFEQemIIX6CKh5bzx0jTRIP3xv92qQcTLqI/eaCtP6iiHzCFjvqAVdQuNWe0QMLF8FI7hOo3yX/f9w X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(767451399110); X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(6040375)(601004)(2401047)(8121501046)(5005006)(3002001)(10201501046)(6055026)(6041248)(20161123555025)(20161123560025)(20161123558025)(20161123562025)(20161123564025)(6072148);SRVR:MWHPR12MB1454;BCL:0;PCL:0;RULEID:;SRVR:MWHPR12MB1454; X-Microsoft-Exchange-Diagnostics: 1;MWHPR12MB1454;4:MMUiFq5+pLKA7TfwTAej1J6LQednV2m1nQIeIzAEFPd+K8o/euSoBCNwy1LHH+V9d7fvXJFy+Yzuez3cH6su4RWXMdZ06jSCz0uuP8K2LSwSgdbSWv4BMj+5cA2ixCLH3TMxdRw8SxZQNvjRpKULHGi9FsiajFIsVcl3v0+KGXQFGrP41W7Mywo+weuesQMBaThW78LnhVq6verChdJdt/QjX6N4TwnXeJF2uWrrcEU1U+cqpCEMeo7w2ybH99OxaPjV3GpkkyccdDGSpJMHLdOwOOcuZgJzWBNBEnqre1ur79Bxk4O5iMcynI974edmIRa8Y1MurJA6maZEdSxoRfuvTLqN9pDRL/mkpJ6+KWVlpwxS3PoBlfRewLgSA/OaGm1eh3oyx2uyQxEfjWHPQoBx0KUfa3jYiGQ6qw6XRiUAK7drGvT+j/zbrUb6/tIDCvQB5LEZbvjNTpvK1JfXFZDS7OZr3DKvNyWr+AClSwzt25GP5lo5fHesCNAIkoRJb77KvNoVgycblXt3slDFGwcg8fA02vvP6km0PB7aWkSCU3oXK0IqGpGsVxR24zzu6vJfVhjY/A5kSG7JHVCAv/CdgA1zXswVCdv6np7Jz5zNfnV/HTZlSL7Lm2A6SmyQ/D3yqPHNlkrgZcpW1Xhq76PdJBZitgWzjPCr/XkmsQw= X-Forefront-PRVS: 02543CD7CD X-Forefront-Antispam-Report: SFV:NSPM;SFS:(10009020)(4630300001)(6009001)(39410400002)(39840400002)(39860400002)(39450400003)(39850400002)(50466002)(189998001)(2950100002)(4326008)(6666003)(6486002)(5660300001)(50226002)(8676002)(5003940100001)(47776003)(66066001)(81166006)(53936002)(6506006)(50986999)(76176999)(4720700003)(54906002)(2906002)(42186005)(38730400002)(7736002)(36756003)(305945005)(6512007)(3846002)(6116002)(86362001)(25786009);DIR:OUT;SFP:1101;SCL:1;SRVR:MWHPR12MB1454;H:ssuthiku-rhel73.localdomain;FPR:;SPF:None;MLV:sfv;LANG:en; X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;MWHPR12MB1454;23:YM82B0sOjDu5Ui9AlYS1lZfFZPg6Y8jHMSpRZqb3t?= =?us-ascii?Q?rc4IiW+jPAKGzyzc82f4yRH47FgTgDtTcj4GHN+LIdYeZEXoD+p+iyQtUGNy?= =?us-ascii?Q?gIP/hRVzF1nlEU9rBYw7a3Zw3rDxZ0dg3zor9wWuduxA5guEFvmDk9YHiyK5?= =?us-ascii?Q?zpngQIHi2ILQJj+okEjlUZrwDt/EOcVLgzoxhV5HV08by8CxdLmeefwEPpqX?= =?us-ascii?Q?zVtOVeErpax2kSsCeYEQX10AcUQ2QRtGNzwrEJM12fwocRQXuR6igip9VsOq?= =?us-ascii?Q?zwYnIrFkhhepkkpDWgzJn0xsVcntkteVnJx+G/CBiM2JhlhzksdXH8xNsk90?= =?us-ascii?Q?LCKhuS3vLl/5nS9QNPiBA/jq/Bx2rTF17WnJOzutGIKRFDarbKwATjdz+I9t?= =?us-ascii?Q?oF2r+1cFKvnxkVRAWfeXwfFD6LRTf4OO9OHsdqFvVuh13TJWpDceXcVM/IEO?= =?us-ascii?Q?vZ3oBn9UZo6snVjCiUhqOz80yDIKW4P368OuUPHFrrAp/H7WOn61UDMlrRS6?= =?us-ascii?Q?M/cZaEDmiYzxYJ/s6U8G5xXGEq5Lxgycd5mhQ+Hks4AIaWAXIjminLab/AnT?= =?us-ascii?Q?MHe9UrF2TR4j0rSA1cfXDYJdfhUPHanM6MYR/TaSAJLPx2rISarO/fxhedUo?= =?us-ascii?Q?x2PGqYLoBIpzhq5GZ61HCnKfbmiP+HkwLoV1jreljhsE3eqEPrYEAZ9rH2rs?= =?us-ascii?Q?OWaXCw0SFhy3aOXyDpzR8GLskFh2gfN7s0MX+w5sLW1G6H9wxS05P1ad1goh?= =?us-ascii?Q?ezeG8zuCXG3D5U3o3RWfhKbgdurtVSDFY7VMIpAv5BMQlpRkWkpuHspDGHes?= =?us-ascii?Q?TQPrKMBfFeWkjr/kWSmG7ecNEnHrVJStAnmoBEmk2IRULYJncCsJDZhWaB/g?= =?us-ascii?Q?2Hx63op9BKOdrqh1jTiHKQNM/bHXh1JnPbiwUSg/NCDUarerXWOWLJQoed8b?= =?us-ascii?Q?WXYmiweeRMvTVNOy6zS+PoYMboinTWcdzlf0kD1+A=3D=3D?= X-Microsoft-Exchange-Diagnostics: 1;MWHPR12MB1454;6:ndGevrZ/RPiWWn+NItGO/sPSiXOtKBtQk5W0kE/DbhZAcK+qi4oKchF8+1Kxxyqp1X7dFbGoMfYhKgqo0J7KOPE2EkF6cys8r3vzriWbzNoB8gi+h4yZ5uQ5Pc7Qkg3mpzel8J2C40u8TuCmNVbHstSDyH9FDnF6CInWAAeA5aP9KVW2kgzK5bGKcdswFrRr/kU6HwBIl5BvCCgPxQ36V5Mjy66T5q66bPNpMO3VxstvEqeatmim65H9Rb2YoDpk1GJCKWAn9yOfJAz/c7rwyl8a+QR+NzrGuQBzUKuU2Cl+Ax690e13fECkaXpvuKhJbNhwxlYiMFbbb7TVheG9Jd+TTOOrE02jGYXv0X/hcNh1ijMukzdvqr4IGGKxMhADe7VHmFmC9lJWFV2bK7FgcYUIk7bgfzFPj6XySkQma/I=;5:o3elZwK10Qy1La7zRabIdv+7gQqR3SHujMjlEf2kW7ZzVn9lfMdnntWVnIWHLcEM8DfZpKf1xYSMUbplADdVvdHyk/P+LrAhKXmLXmg6eLgnzdvJ9ur2fbpjl0iiv+Grpqk0g3aBOh1Nz7DPxCc2fw==;24:8Ibl2W1dWIyGmr+OB5sL/QAvdRx7Y9IqSXc6Sze8kr9a/wwseqql11TZTmVJ9TAH0d3Y2JiNJY++r6vJsYw5b0R/qrBziDemX6UIM0xeUa4= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1;MWHPR12MB1454;7:0K5MOoWG+FA3l6UWdKryu8nFdqcJg6jzF7h96iaqeAmr+ZNFFVfH9+1W7Y/qBBeMEZCk337ylhCM/FET2058l0UQcB1KYtCKYD+cwfaId4rp5DgnZXxIA8m8EFVcwx994+vPUdRP0Uc0bcf/UklNu5AUsWldBrsbCPF/s84zx+9g8n7FiStGVSXjLTRR4dNxKX31sHsIBlIZEyr2eteHZUF1jawnoCOY3OJDu6okame28U6BmBsC4qXV6KRnLS6LCKUwnxRrq6SvS8u3bYX1YhjurlAWG1DNl732aofVPuZQC7QkU8IsfOKPWR+7YMPhm6iOrNhZj0LSaUizWlt5wg==;20:nvYvgXXrPlYMUs/rlKgRJNaRsyNW5pw09hHp9pyp0TLDOvsUSK9kIUABliNaCGXD6o/Sg6908eTLv9o2RtNqXjlFyE3LE4U8zuvJOCnkqZjTwfkZGcp0BDFxsK10pg0e9aQMb6sCYdd+iTUGWfLK7gSg6GbMDVA9CeVxQoLcqX5JNgMFBuxk2wVyW8x95bJlU7C0Rjmm6l52ubscIpz3fEeJjN3lo98Nj3g05lT/b7x1ojE7m5tv2lfLeT+HTZ/9 X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 22 Mar 2017 07:04:00.1282 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: MWHPR12MB1454 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 6610 Lines: 217 From: Suravee Suthikulpanit Add multi-IOMMU support for perf by exposing an AMD IOMMU PMU for each IOMMU found in the system via: /bus/event_source/devices/amd_iommu_x where x is the IOMMU index. This allows users to specify different events to be programmed onto performance counters of each IOMMU. Cc: Borislav Petkov Cc: Peter Zijlstra Signed-off-by: Suravee Suthikulpanit --- arch/x86/events/amd/iommu.c | 111 ++++++++++++++++++++++++++++---------------- 1 file changed, 70 insertions(+), 41 deletions(-) diff --git a/arch/x86/events/amd/iommu.c b/arch/x86/events/amd/iommu.c index 915a20c..9a12077 100644 --- a/arch/x86/events/amd/iommu.c +++ b/arch/x86/events/amd/iommu.c @@ -34,16 +34,21 @@ #define GET_DOMID_MASK(x) ((x->conf1 >> 16) & 0xFFFFULL) #define GET_PASID_MASK(x) ((x->conf1 >> 32) & 0xFFFFFULL) -static struct perf_amd_iommu __perf_iommu; +#define PERF_AMD_IOMMU_NAME_SIZE 16 struct perf_amd_iommu { + struct list_head list; struct pmu pmu; + struct amd_iommu *iommu; + char name[PERF_AMD_IOMMU_NAME_SIZE]; u8 max_banks; u8 max_counters; u64 cntr_assign_mask; raw_spinlock_t lock; }; +static LIST_HEAD(perf_amd_iommu_list); + /*--------------------------------------------- * sysfs format attributes *---------------------------------------------*/ @@ -234,9 +239,14 @@ static int perf_iommu_event_init(struct perf_event *event) return 0; } +static inline struct amd_iommu *perf_event_2_iommu(struct perf_event *ev) +{ + return (container_of(ev->pmu, struct perf_amd_iommu, pmu))->iommu; +} + static void perf_iommu_enable_event(struct perf_event *ev) { - struct amd_iommu *iommu = get_amd_iommu(0); + struct amd_iommu *iommu = perf_event_2_iommu(ev); struct hw_perf_event *hwc = &ev->hw; u8 bank = hwc->iommu_bank; u8 cntr = hwc->iommu_cntr; @@ -266,7 +276,7 @@ static void perf_iommu_enable_event(struct perf_event *ev) static void perf_iommu_disable_event(struct perf_event *event) { - struct amd_iommu *iommu = get_amd_iommu(0); + struct amd_iommu *iommu = perf_event_2_iommu(event); struct hw_perf_event *hwc = &event->hw; u64 reg = 0ULL; @@ -286,7 +296,7 @@ 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); - struct amd_iommu *iommu = get_amd_iommu(0); + struct amd_iommu *iommu = perf_event_2_iommu(event); amd_iommu_pc_set_reg(iommu, hwc->iommu_bank, hwc->iommu_cntr, IOMMU_PC_COUNTER_REG, &prev_raw_count); @@ -301,7 +311,7 @@ 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); + struct amd_iommu *iommu = perf_event_2_iommu(event); if (amd_iommu_pc_get_reg(iommu, hwc->iommu_bank, hwc->iommu_cntr, IOMMU_PC_COUNTER_REG, &count)) @@ -389,11 +399,6 @@ static __init int _init_events_attrs(void) return 0; } -static __init void amd_iommu_pc_exit(void) -{ - kfree(amd_iommu_events_group.attrs); -} - const struct attribute_group *amd_iommu_attr_groups[] = { &amd_iommu_format_group, &amd_iommu_cpumask_group, @@ -401,47 +406,56 @@ static __init void amd_iommu_pc_exit(void) NULL, }; +static struct pmu iommu_pmu = { + .event_init = perf_iommu_event_init, + .add = perf_iommu_add, + .del = perf_iommu_del, + .start = perf_iommu_start, + .stop = perf_iommu_stop, + .read = perf_iommu_read, + .task_ctx_nr = perf_invalid_context, + .attr_groups = amd_iommu_attr_groups, +}; + static __init int -_init_perf_amd_iommu(struct perf_amd_iommu *perf_iommu, char *name) +init_one_iommu(unsigned int idx) { int ret; + struct perf_amd_iommu *perf_iommu; - raw_spin_lock_init(&perf_iommu->lock); + perf_iommu = kzalloc(sizeof(struct perf_amd_iommu), GFP_KERNEL); + if (!perf_iommu) + return -ENOMEM; - /* Init cpumask attributes to only core 0 */ - cpumask_set_cpu(0, &iommu_cpumask); + raw_spin_lock_init(&perf_iommu->lock); - 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) + perf_iommu->pmu = iommu_pmu; + perf_iommu->iommu = get_amd_iommu(idx); + perf_iommu->max_banks = amd_iommu_pc_get_max_banks(idx); + perf_iommu->max_counters = amd_iommu_pc_get_max_counters(idx); + if (!perf_iommu->iommu || !perf_iommu->max_banks || + !perf_iommu->max_counters) { + kfree(perf_iommu); return -EINVAL; + } - perf_iommu->pmu.attr_groups = amd_iommu_attr_groups; - ret = perf_pmu_register(&perf_iommu->pmu, name, -1); - if (ret) - pr_err("Error initializing AMD IOMMU perf counters.\n"); - else - pr_info("Detected AMD IOMMU (%d banks, %d counters/bank).\n", - amd_iommu_pc_get_max_banks(0), - amd_iommu_pc_get_max_counters(0)); + snprintf(perf_iommu->name, PERF_AMD_IOMMU_NAME_SIZE, "amd_iommu_%u", idx); + ret = perf_pmu_register(&perf_iommu->pmu, perf_iommu->name, -1); + if (!ret) { + pr_info("Detected AMD IOMMU #%d (%d banks, %d counters/bank).\n", + idx, perf_iommu->max_banks, perf_iommu->max_counters); + list_add_tail(&perf_iommu->list, &perf_amd_iommu_list); + } else { + pr_warn("Error initializing IOMMU %d.\n", idx); + kfree(perf_iommu); + } return ret; } -static struct perf_amd_iommu __perf_iommu = { - .pmu = { - .task_ctx_nr = perf_invalid_context, - .event_init = perf_iommu_event_init, - .add = perf_iommu_add, - .del = perf_iommu_del, - .start = perf_iommu_start, - .stop = perf_iommu_stop, - .read = perf_iommu_read, - }, -}; - static __init int amd_iommu_pc_init(void) { int ret; + unsigned int i, cnt = 0; /* Make sure the IOMMU PC resource is available */ if (!amd_iommu_pc_supported()) @@ -451,11 +465,26 @@ static __init int amd_iommu_pc_init(void) if (ret) return ret; - ret = _init_perf_amd_iommu(&__perf_iommu, "amd_iommu"); - if (ret) - amd_iommu_pc_exit(); + /* + * An IOMMU PMU is specific to each IOMMU, and can + * function independently. So, we go through all IOMMUs + * and ignore the one that fails initialization unless + * all IOMMU are failing. + */ + for (i = 0; i < amd_iommu_get_num_iommus(); i++) { + ret = init_one_iommu(i); + if (!ret) + cnt++; + } - return ret; + if (!cnt) { + kfree(amd_iommu_events_group.attrs); + return -ENODEV; + } + + /* Init cpumask attributes to only core 0 */ + cpumask_set_cpu(0, &iommu_cpumask); + return 0; } device_initcall(amd_iommu_pc_init); -- 1.8.3.1