From patchwork Tue Sep 26 22:23:24 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Al Stone X-Patchwork-Id: 9972803 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id EAB306037E for ; Tue, 26 Sep 2017 22:33:56 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DE86428BCD for ; Tue, 26 Sep 2017 22:33:56 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D394728FA6; Tue, 26 Sep 2017 22:33:56 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,RCVD_IN_DNSWL_MED autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 3913928BCD for ; Tue, 26 Sep 2017 22:33:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=uk5Ih8djhSrgyeXHQDAIOe7kB4xuhdSGIciVu+5QBS4=; b=AkI1srDFVYHb7vmQkO1JHkP8Kv Q4CmcfF+KqxVsPCbFHRODMzzqZna2veb5jCgWD3ftBInWnqh5e8/3S1KUW6qS7JfNt5NDZBctPnYl xpiv9UfRqPMjlzaBhd+ypCYct6W3K3jb2Z8jn70Nz+K9PYXYbkPeXkaswafDgbwmhiR0MSpEfP+iZ h1hKcjNe6oEGbkhI303nQLfeZEJJGjfvHlSauUNNfDmFnt+CWHSEP/Ki+DwbHcQ81RhYm9qum3Ox/ Ky4+VbQLk1QOQSGBJTxzqx3OiKbN2MotS/2kHDCUyLfQp6DovaXKePYuwJIYDpURjSBhlVHMJvz6/ IfojefQA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1dwyQN-0008I2-Ic; Tue, 26 Sep 2017 22:33:55 +0000 Received: from mx1.redhat.com ([209.132.183.28]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1dwyGo-0005pZ-Ky for linux-arm-kernel@lists.infradead.org; Tue, 26 Sep 2017 22:24:06 +0000 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 010BB83F40; Tue, 26 Sep 2017 22:23:43 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 010BB83F40 Authentication-Results: ext-mx03.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx03.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=ahs3@redhat.com Received: from fidelio.ahs3 (ovpn-116-41.phx2.redhat.com [10.3.116.41]) by smtp.corp.redhat.com (Postfix) with ESMTP id 876A7783BA; Tue, 26 Sep 2017 22:23:42 +0000 (UTC) From: Al Stone To: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH 3/3] arm64: cpuinfo: display product info in /proc/cpuinfo Date: Tue, 26 Sep 2017 16:23:24 -0600 Message-Id: <20170926222324.17409-4-ahs3@redhat.com> In-Reply-To: <20170926222324.17409-1-ahs3@redhat.com> References: <20170926222324.17409-1-ahs3@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Tue, 26 Sep 2017 22:23:43 +0000 (UTC) X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20170926_152402_768494_A2B5F49F X-CRM114-Status: GOOD ( 19.30 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Mark Rutland , Catalin Marinas , Will Deacon , Al Stone , Suzuki K Poulose MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP While it is very useful to know what CPU is being used, it is also useful to know who made the platform being used. On servers, this can point to the right person to contact when a server is having trouble. Go get the product info -- manufacturer, product name and version -- from DMI (aka SMBIOS) and display it in /proc/cpuinfo. To look more like other server platforms, include the CPU type and frequency when displaying the product info, too. Signed-off-by: Al Stone Cc: Catalin Marinas Cc: Will Deacon Cc: Suzuki K Poulose Cc: Mark Rutland --- arch/arm64/kernel/cpuinfo.c | 135 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 134 insertions(+), 1 deletion(-) diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c index 0b4261884862..6a9dbad5ee3f 100644 --- a/arch/arm64/kernel/cpuinfo.c +++ b/arch/arm64/kernel/cpuinfo.c @@ -19,10 +19,12 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -31,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -167,6 +170,111 @@ static const char *const compat_hwcap2_str[] = { }; #endif /* CONFIG_COMPAT */ +/* Details needed when extracting fields from DMI info */ +#define DMI_ENTRY_BASEBOARD_MIN_LENGTH 8 +#define DMI_ENTRY_PROCESSOR_MIN_LENGTH 48 + +#define DMI_BASEBOARD_MANUFACTURER 0x04 +#define DMI_BASEBOARD_PRODUCT 0x05 +#define DMI_BASEBOARD_VERSION 0x06 +#define DMI_PROCESSOR_MAX_SPEED 0x14 + +#define DMI_MAX_STRLEN 80 + +/* Values captured from DMI info */ +static u64 dmi_max_mhz; +static char *dmi_product_info; + +/* Callback function used to retrieve the max frequency from DMI */ +static void find_dmi_mhz(const struct dmi_header *dm, void *private) +{ + const u8 *dmi_data = (const u8 *)dm; + u16 *mhz = (u16 *)private; + + if (dm->type == DMI_ENTRY_PROCESSOR && + dm->length >= DMI_ENTRY_PROCESSOR_MIN_LENGTH) { + u16 val = (u16)get_unaligned((const u16 *) + (dmi_data + DMI_PROCESSOR_MAX_SPEED)); + *mhz = val > *mhz ? val : *mhz; + } +} + +/* Look up the max frequency in DMI */ +static u64 get_dmi_max_mhz(void) +{ + u16 mhz = 0; + + dmi_walk(find_dmi_mhz, &mhz); + + /* + * Real stupid fallback value, just in case there is no + * actual value set. + */ + mhz = mhz ? mhz : 1; + + return (u64)mhz; +} + +/* Helper function for the product info callback */ +static char *copy_string_n(char *dst, char *table, int idx) +{ + char *d = dst; + char *ptr = table; + int ii; + + /* skip the first idx-1 strings */ + for (ii = 1; ii < idx; ii++) { + while (*ptr) + ptr++; + ptr++; + } + + /* copy in the string we need */ + while (*ptr && (d - dst) < (DMI_MAX_STRLEN - 2)) + *d++ = *ptr++; + + return d; +} + +/* Callback function used to retrieve the product info DMI */ +static void find_dmi_product_info(const struct dmi_header *dm, void *private) +{ + const u8 *dmi_data = (const u8 *)dm; + char *ptr = (char *)private; + + if (dm->type == DMI_ENTRY_BASEBOARD && + dm->length >= DMI_ENTRY_BASEBOARD_MIN_LENGTH) { + int idx; + + idx = (int)get_unaligned((const u8 *) + (dmi_data + DMI_BASEBOARD_MANUFACTURER)); + ptr = copy_string_n(ptr, (char *)(dmi_data + dm->length), idx); + *ptr++ = ' '; + + idx = (int)get_unaligned((const u8 *) + (dmi_data + DMI_BASEBOARD_PRODUCT)); + ptr = copy_string_n(ptr, (char *)(dmi_data + dm->length), idx); + *ptr++ = ' '; + + idx = (int)get_unaligned((const u8 *) + (dmi_data + DMI_BASEBOARD_VERSION)); + ptr = copy_string_n(ptr, (char *)(dmi_data + dm->length), idx); + } +} + +/* Look up the baseboard info in DMI */ +static void get_dmi_product_info(void) +{ + if (!dmi_product_info) { + dmi_product_info = kcalloc(DMI_MAX_STRLEN, + sizeof(char), GFP_KERNEL); + if (!dmi_product_info) + return; + } + + dmi_walk(find_dmi_product_info, dmi_product_info); +} + static int c_show(struct seq_file *m, void *v) { int i, j; @@ -190,6 +298,31 @@ static int c_show(struct seq_file *m, void *v) seq_printf(m, "model name\t: ARMv8 Processor rev %d (%s)\n", MIDR_REVISION(midr), COMPAT_ELF_PLATFORM); + if (IS_ENABLED(CONFIG_DMI)) { + seq_puts(m, "product name\t: "); + + if (!dmi_product_info) + get_dmi_product_info(); + if (dmi_product_info) + seq_printf(m, "%s", dmi_product_info); + else + seq_puts(m, ""); + + seq_printf(m, ", ARM 8.%d (r%dp%d) CPU", + MIDR_VARIANT(midr), + MIDR_VARIANT(midr), + MIDR_REVISION(midr)); + + if (!dmi_max_mhz) + dmi_max_mhz = get_dmi_max_mhz(); + if (dmi_max_mhz) + seq_printf(m, " @ %d.%02dGHz\n", + (int)(dmi_max_mhz / 1000), + (int)(dmi_max_mhz % 1000)); + else + seq_puts(m, " @ GHz\n"); + } + impl = (u8) MIDR_IMPLEMENTOR(midr); for (j = 0; hw_implementer[j].id != 0; j++) { if (hw_implementer[j].id == impl) { @@ -208,7 +341,7 @@ static int c_show(struct seq_file *m, void *v) part = (u16) MIDR_PARTNUM(midr); for (j = 0; parts[j].id != (-1); j++) { if (parts[j].id == part) { - seq_printf(m, "%s\n", parts[j].name); + seq_printf(m, "%s ", parts[j].name); break; } }