From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751800AbdBXIyG (ORCPT ); Fri, 24 Feb 2017 03:54:06 -0500 Received: from mail-cys01nam02on0041.outbound.protection.outlook.com ([104.47.37.41]:50240 "EHLO NAM02-CY1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751342AbdBXIwx (ORCPT ); Fri, 24 Feb 2017 03:52:53 -0500 Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=Suravee.Suthikulpanit@amd.com; From: Suravee Suthikulpanit To: , CC: , , , , Suravee Suthikulpanit , Suravee Suthikulpanit Subject: [PATCH v11 10/10] perf/amd/iommu: Enable support for multiple IOMMUs Date: Fri, 24 Feb 2017 02:48:22 -0600 Message-ID: <1487926102-13073-11-git-send-email-Suravee.Suthikulpanit@amd.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1487926102-13073-1-git-send-email-Suravee.Suthikulpanit@amd.com> References: <1487926102-13073-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: HK2PR02CA0037.apcprd02.prod.outlook.com (10.163.104.175) To CY4PR12MB1447.namprd12.prod.outlook.com (10.172.71.139) X-MS-Office365-Filtering-Correlation-Id: 455c3361-22c3-4fb8-12c5-08d45c921c4d X-MS-Office365-Filtering-HT: Tenant X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:(22001)(48565401081);SRVR:CY4PR12MB1447; X-Microsoft-Exchange-Diagnostics: 1;CY4PR12MB1447;3:wPA6ibzy0Uy0UqkoTn2RgTTFp9gaEpVu3YuQnKZoNO+Zxn7FmqCBVcyBh8BmDbL6hBt1FbXx1lrQfr2TZuOhsTB5gT2TeLwIFnMjuL2ymSAeMo1WieNPNiPObflHk5G3i73uJ08dCFD1+2wL8Z5dxkHhu9LyhJeFafpnp6Ise12fEdODX5U8vDCQ4h7d1fkOS94LuraES1r2oO/tO+l2zs9W3OVk5CttsV9hRbSUtBMbX02wj3EynR8SPsPnKMn6nLxASKInEOwv9OpsZyi2mqJJ5M7285x8pG5wdR/f/jI=;25:t2lKw5YqyMDif5beizPsAg9MAjM41/Gxu1pq3FfAhaFK8E9JNOrMZFvnlDRCAJG4P/oH5QgiSesKmNe1aa1H7yXVsPo4qq5oN+JBh5RtlvuqVT1QbCCxftd2jpaZ3S3MBIgikhikGP1Uon8W9W7cyoIClzSWNHcd53mdOMVwLG7aJLH59iVY1j0lCXqLNYOQUkGcx5b/USsxWkCwmi8LldPRPwc/nuOYYqLt7LZmvUrb+L7r705+yuRk6iC8Xr8OtL0H6is1I03To8UrsqXGhc5Yy1cA9kuim7yULmoq0Q2rSmbmXe9asjQuIZapIv5wfHlysE0ZSZJU34Sc8FVLp/XvRlsQ88ZdIq53F5wg8fBuYwYvx5AoZ91IgPJOPFL893wYzymsHOqCikrLHVB3+5TPTF2bn1i9tbXVMOF1XpL8SF4wWgGhIwr3S7pIxXfRW5dlbm4sz5VAcoz/k4glWA== X-Microsoft-Exchange-Diagnostics: 1;CY4PR12MB1447;31:+meZaLHh6/98cAdWnxee2VJvfJd4npJgEA5sJlWtG0usQUuoTp4T6ZQjtfL4RF4HKakZMUEpvMyXEB2tGwtXf5Cz9Fxy28ObJ9YdwcdJoD4Qo/7iip0I7Nf7v4QMvvFhdUxDFUO2AcW/DWQ0bAryMeqfCMqF4rVKvNf6DeNgk7XqcqE2Cs1kBjBpyZmDPyY0FajBXilcRfT/tnwwkj1mSP8AvofVGOkUQhzfACdW3eM=;20:alGHzJ6OcVIvGBh0Jh3AhCXoFqpJ+hreKFPor09zf5wkt3n0vbbAda7j8d/WADCYOJqA0P/KmfPKTZoCko+RP5eEEylwk2A6l4ORM47/+WeU445m9BZtssQwJTepWcjzHo2V/bOKhS+ha360HfMzJAg3xDi7zVSjjW0kRf9k2FuqEbDvfVc4go8vgc6utKbhe1Ku8o5hsQVUe1yySbomSBNfeKZb0M4ZSQHwSmrAHy4vegFE442M3ljbrMFIMpnZIc/aCbtuKUVRnqyOcmxwlEtGoVzsb87Sy7nPlPuh3nN361rIj5N1GlVhf8E+X1n1Fqe0m8eMyZ3JOVeyRpX0WVX2N/H+9aSXp7iVQnn+CqCXS+vISwFEeADIYovBKOXEY87MR4EGg/koP9l9n4TBPgf6VkBd3kDs3VWCGeu3S/RlLvgiftiDKCcAT4zl/M50/qJcS/TE9kdA8/Qg1iifVqRL67JR2tEfQONkqQE51YS+2AdSCJzJ+KPCQ6eoQIWV 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)(20161123558025)(20161123564025)(20161123560025)(20161123555025)(20161123562025)(6072148);SRVR:CY4PR12MB1447;BCL:0;PCL:0;RULEID:;SRVR:CY4PR12MB1447; X-Microsoft-Exchange-Diagnostics: 1;CY4PR12MB1447;4:30K4KhzXeg/UCKGOYnz6+uLXOmZrYUepNqOoiOiI/Sic7j134yW113pSU1WqZwjnQNZcWDsqbKsCFJGjiusPNEZIc0UwiJs96RiXKMIbLPWmPZD9j6OulzbRuve8YdHNMKfCkdhNDHEOO1nYiu2vUPmyuh7jG6uPMvqLsOqWprAzQrgkkGwgRK25QsERH2Uz6aizeLTBSIvSZe51PtHUdKakXkkg/0PvUW78/U6ZbCDmxkO7V5qX+PIWK7gQr/WkrsDbJGobA97saRhJ6xLc3d/CvsqZ/n4juYWPjnXTrwMkh1NCI7S1Z2mPp1WXTtsl016vxTRKKHLUB+3JvS1G/pFw+zKJ6yWwLK4dYffheTKG7bJmIzjK8Un2MMKyx2RrPgm77j7Ckeka5m5U8HSeOFiIdGBpnPpCI6zkfk74CHr7vTyi9+46sDedKKOg8m6/3ObepEVnzglB+BIfsC2tmTnwsW6zY5GzGe8ICuyeUt9nXVwf4WYF6Uh+nQT4b6Q32lxOek8O3LGKzULs/2tx75wdwCPHtj+t+5PCrkqKEiNEO0/wq7Oe/RfCnwK5Q6ApBeQDgeZgDRI/29d4s5M5Sobfk5KWXLo9tAUb3UAlA5Ho5nVi9f6T2lMWQ07Xr7WkIg5+gY9V9QwesK8Mq/A2hY0s/44uvxmgRCqMLtFmVSo= X-Forefront-PRVS: 0228DDDDD7 X-Forefront-Antispam-Report: SFV:NSPM;SFS:(10009020)(4630300001)(6009001)(7916002)(39860400002)(39850400002)(39410400002)(39840400002)(39450400003)(189002)(199003)(3846002)(4326007)(105586002)(47776003)(6116002)(76176999)(305945005)(36756003)(86362001)(50986999)(6506006)(101416001)(106356001)(38730400002)(53936002)(6486002)(7736002)(66066001)(68736007)(25786008)(8676002)(48376002)(5660300001)(5003940100001)(54906002)(92566002)(2906002)(189998001)(50466002)(6666003)(81156014)(2950100002)(4720700003)(50226002)(6512007)(81166006)(97736004)(42186005);DIR:OUT;SFP:1101;SCL:1;SRVR:CY4PR12MB1447;H:ssuthiku-rhel73.localdomain;FPR:;SPF:None;PTR:InfoNoRecords;MX:1;A:1;LANG:en; X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;CY4PR12MB1447;23:aX50FYVZ9kppHAdgwES2WhPpE0/AMWYEsr0Yx5zQE?= =?us-ascii?Q?WMWL/KXXUsGxQ+XtwsDzCQXj8Zf2bNHWtpyS0KvNQaSpOAJfBOofU4h6nENX?= =?us-ascii?Q?lFiLVNBduiTPoLYPCCbljzBS2aVBpJJCavJz1jiu396lC/ChGDms+nHhPom7?= =?us-ascii?Q?W8MeWejRE3jqf74KbhfIJDRBqtpZjlMOYFoQxIeQb+67HYhpmg0uSWPUCmwM?= =?us-ascii?Q?nNveGedeS5q+LbtUYlAgY1vlRBMQ3hF2gyfMJclKf2E7qKVgRdvh3hR/aYzA?= =?us-ascii?Q?9NL1DyeXXuiRcXJ8oxJY3UQ5QrsobLXj4EzgqXb9o1vcJ9ut7ZfW2D4aiILf?= =?us-ascii?Q?XIpDLeE5zKo2OSuKLea8HR0pS8J6IzOyaVFBK4yulbGU7x5pCD4V00ZVrnqz?= =?us-ascii?Q?9fZWJkqdTPm6Jtdz2T7P63MufxE7EJ93UT/tX2pWRoCmg0tTOtTKvFQfTA4K?= =?us-ascii?Q?BCF+GEDrzoEMzxTnZAWp/tET+2oHLD5xJEjuJ4xTlRhStQrWWrU244Osij4I?= =?us-ascii?Q?+5RWJ9bi84K5ALbwiOp+Nynk333NWPAlXyjZDX5kr6JlvUjAURbk38SlkL5m?= =?us-ascii?Q?q88TDqfywiCoamhDYh+3NqElCZQW3mt0c2IvSRF+gA9YM03EGOqxzAAdx3On?= =?us-ascii?Q?qiBuCuj1hdQjvRrCFMgfcTVxVdLmBY8M7Zl4JAfkHQHnK71fa4KBIFa2LP3L?= =?us-ascii?Q?0mVqTlN7YcjV0poBrnBH4vMovRxy3TosRZoXzzXuzFgiYLckr0QGakNjMsCh?= =?us-ascii?Q?o5J6IcmYQfh8QmLqvfCewsQKUCBkfe5g/4e8qd4IcdUOAZL+6gk/KrJqwo+2?= =?us-ascii?Q?yw2O9V7eJjSh4FwnEdcSLKWtaWuL+Qrup2Ryr8pftABghN+ccD/lMebPKGgo?= =?us-ascii?Q?2OnkGHbsSVm981C9BO8erhn6Vf5ngvujFsWTU50+MMMANeoCEM4f3C0dF9YF?= =?us-ascii?Q?I1FZsji2ZSK41MWZ5Ho8Vf+9W87vbCOp0bto0JQPChbgLbmFIdFmB85dLDTC?= =?us-ascii?Q?mWRzJ3aXtTj52LlB1ZXdkH1eGcBGEnMozJCtVlp5BIdLXPuBXEH6e6w5FswY?= =?us-ascii?Q?tgPrEmdaF7sO9Yeq3CsRZENxrKxPomn6UypH2NK801I7YPY8KEmDWV2ugy9w?= =?us-ascii?Q?OPolaT0FXvW46v+d56KUst5+UNMULLJFGjqSdyAATRdHbzDGyvr8I7y/tAwn?= =?us-ascii?Q?q9i1RCpRGPbSt8=3D?= X-Microsoft-Exchange-Diagnostics: 1;CY4PR12MB1447;6:vRG5FuIlG2b/gUGhwrTpv/TIv8iA/ueLEQy5/ACYwi6olhqGP+k0E/c5JuAMsQRPHzU5jI9aTzb6+U0yAO1CEx+VdZ1/Z5iuSvrPEfCqkJyG0o6lT8kbtXmpBuEeafzsFrQCh99lughtq+J1QRMPjyGWFndDcNPaozYfzBRZJKkL8EhIYKMAnHng4MCPgNW2VzlLYFtKejLjwEEfyVd/0cL44qaHM5594Su0vwAeFkMPcYg0Byf6c9ew/+m4p4ebVVTQfIsyq+cdhELQi0kGzcIOPlajjQPVBcP/xpVmO2i7YCR2FfFZgQIUhBf6hoSta/R7WDC/UHKMcw8iBq/iQwzm58L1S2AKhfRVX/sv/u8VwthPcn5Ths9AJWKfMZ8HDJqWo++LdkfTLFhiJD//IsP9mLXfe2wDqfXsTmOXPK0=;5:Y8tsFJdjemujhn59LbjHHjc3Kvk47G4XJREIiq9wgR69nv96jYwduMRBX/9JVF5SDhjBp4mifD9UG+1nSYvT27gGFISsl5wmYQTzRo+HSf1A9lCOBsIkzkJ4zmSsuHCsGm9ykDy97IYEorPqPBmpJ2FVPomOS9xah74gHM315CI=;24:0Q3ilWIq807pJKpORuZNzX56lax3xbATvILXFEb9Zq70NnJfdjTXLSKnKtT8M7hQ7YbUcM++nTqkuuC/+VcsAkWfPAY5O49+zPh255WJH3g= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1;CY4PR12MB1447;7:iVKSquHRj0XIX4HhdzURip+J/mOlOelqJtv0BvjnPk0nLn3hcP2frInkSZia4T0G4DS75KRODsTwzGK64DEaI+sYdsV4fB+X4/pf1LUuc7EFk9fLjd8KEb2DeQ6gBvBK4x+286jaR0aPXZLkU05iTSpC5iP3lkbzlb3RCWoz7erBghzpmMNy482bqH/Vo+VYprpfY0bqF5260P56n9C0nd5RZqf0BqYem3Ttbwas3OgL+v43g/OPwwz52LwVvTb5EVzASid+EJzZLiGKs2ZhV9SS6crfuNFmtscc7midKRgl4ENTtk8XsGpNqdgj9rrEOflqkod249tmpdB/SXdzFA==;20:Wld4uCNmNTv19uLxnCEdDbnIbe2Y7d0YtYxfcC803ZIPpi9+CoN8q0bPezNNN/6oF/6YoPabtsxVzke6q13sxZebXCJUCHIscyqbsBfnLSRPM4JQEUA33KFJfLJSUfYW/eyxgMYHla//+n9CdBRyvnjbZS2OWIOU/1ytvT3KanPCX3fJnroc5QXU15Qpi4fAf3QOLiiaQ161kOJlcNTO3VZJqChka4rmdb6oDoU9A00H/6LU72q7yjE/gFj4j1MH X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 24 Feb 2017 08:49:49.8962 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: CY4PR12MB1447 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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 | 125 +++++++++++++++++++++++++------------------- 1 file changed, 70 insertions(+), 55 deletions(-) diff --git a/arch/x86/events/amd/iommu.c b/arch/x86/events/amd/iommu.c index 5cc7c14..a1d12f4 100644 --- a/arch/x86/events/amd/iommu.c +++ b/arch/x86/events/amd/iommu.c @@ -34,16 +34,21 @@ #define GET_DOMID_MASK(c) ((c >> 16) & 0xFFFFULL) #define GET_PASID_MASK(c) ((c >> 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 *---------------------------------------------*/ @@ -206,8 +211,6 @@ static int clear_avail_iommu_bnk_cntr(struct perf_amd_iommu *perf_iommu, static int perf_iommu_event_init(struct perf_event *event) { struct hw_perf_event *hwc = &event->hw; - struct perf_amd_iommu *perf_iommu; - u64 config, config1; /* test the event attr type check for PMU enumeration */ if (event->attr.type != event->pmu->type) @@ -229,18 +232,6 @@ static int perf_iommu_event_init(struct perf_event *event) if (event->cpu < 0) return -EINVAL; - perf_iommu = &__perf_iommu; - - if (event->pmu != &perf_iommu->pmu) - return -ENOENT; - - if (perf_iommu) { - config = event->attr.config; - config1 = event->attr.config1; - } else { - return -EINVAL; - } - /* update the hw_perf_event struct with the iommu config data */ hwc->iommu_csource = GET_CSOURCE(event->attr.config); hwc->iommu_devid = GET_DEVID(event->attr.config); @@ -253,9 +244,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; @@ -285,7 +281,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; @@ -305,7 +301,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); @@ -320,7 +316,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)) @@ -408,11 +404,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, @@ -420,47 +411,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()) @@ -470,11 +470,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