From patchwork Mon Mar 20 00:09:36 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Haozhong Zhang X-Patchwork-Id: 9632873 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 F30786020B for ; Mon, 20 Mar 2017 00:15:45 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E66AF27F9F for ; Mon, 20 Mar 2017 00:15:45 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id DB4A227FBC; Mon, 20 Mar 2017 00:15:45 +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.1 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id E4C2C27F8C for ; Mon, 20 Mar 2017 00:15:44 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1cpkwi-0006St-4G; Mon, 20 Mar 2017 00:13:12 +0000 Received: from mail6.bemta3.messagelabs.com ([195.245.230.39]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1cpkwg-0006Rw-O2 for xen-devel@lists.xen.org; Mon, 20 Mar 2017 00:13:10 +0000 Received: from [85.158.137.68] by server-12.bemta-3.messagelabs.com id C8/4F-12861-69E1FC85; Mon, 20 Mar 2017 00:13:10 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFmpnkeJIrShJLcpLzFFi42I5YG5SrDtV7ny Ewbs5IhZLPi5mcWD0OLr7N1MAYxRrZl5SfkUCa8bTfZtZClriK1btWMTcwLjMp4uRk4NF4BaT xOK3il2MXBxCAtMZJX6tmcgEkpAQ4JU4smwGK4TtJzH933kWiKJeRolZU7eCJdgE9CVWPD4IZ osISEtc+3yZEaSIWeAio8S225vZuxg5OIQF3CVWPcuB2KYqcWTpexYQm1fAVmLm8l5GiAXyEh eungKLcwrYSay5dJsdxBYCqtl/axrbBEa+BYwMqxg1ilOLylKLdA0t9ZKKMtMzSnITM3N0DQ2 M9XJTi4sT01NzEpOK9ZLzczcxAgOlnoGBcQfj7+N+hxglOZiURHn/qZ+LEOJLyk+pzEgszogv Ks1JLT7EKMPBoSTBWyt7PkJIsCg1PbUiLTMHGLIwaQkOHiURXjlg2ArxFhck5hZnpkOkTjHqc iz6t/sNkxBLXn5eqpQ47wyQGQIgRRmleXAjYPFziVFWSpiXkYGBQYinILUoN7MEVf4VozgHo5 IwbxfIFJ7MvBK4Ta+AjmACOmLZjTMgR5QkIqSkGhj1Fiv+aT99v0V6qbaIj/9qS72e7N4jMSy feya+EJ9QP9WAR+ktrx3n5r6ihxtMzk2asjhBviY4o0/Fd/6qJddU1lycy+Ikrbiz2jNS9q76 V449P6xdPrktsb94zPJUwmLxO1fVInyVetfZtE65l8anNFuqs78+r63nXfKqt3E2fLFXTTqe9 CqxFGckGmoxFxUnAgAgXmPkmgIAAA== X-Env-Sender: haozhong.zhang@intel.com X-Msg-Ref: server-3.tower-31.messagelabs.com!1489968786!90971295!2 X-Originating-IP: [192.55.52.115] X-SpamReason: No, hits=0.5 required=7.0 tests=BODY_RANDOM_LONG X-StarScan-Received: X-StarScan-Version: 9.2.3; banners=-,-,- X-VirusChecked: Checked Received: (qmail 20066 invoked from network); 20 Mar 2017 00:13:09 -0000 Received: from mga14.intel.com (HELO mga14.intel.com) (192.55.52.115) by server-3.tower-31.messagelabs.com with DHE-RSA-AES256-GCM-SHA384 encrypted SMTP; 20 Mar 2017 00:13:09 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=intel.com; i=@intel.com; q=dns/txt; s=intel; t=1489968789; x=1521504789; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=ADsPO3hwB6hU745CkuZBBlXTRGWm4LZieW+QIZ/j3CY=; b=M/+VaWNqxmiBJ8rLYvqNnNo1uuyA8yYMU1U98RTqcSFBtSNCUv2EiefB vJjSfJndy2t4kVqDZW8NTkqhS7ZfzQ==; Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by fmsmga103.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 19 Mar 2017 17:13:05 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.36,191,1486454400"; d="scan'208";a="78799155" Received: from hz-desktop.sh.intel.com (HELO localhost) ([10.239.159.153]) by fmsmga006.fm.intel.com with ESMTP; 19 Mar 2017 17:13:04 -0700 From: Haozhong Zhang To: xen-devel@lists.xen.org Date: Mon, 20 Mar 2017 08:09:36 +0800 Message-Id: <20170320000949.24675-3-haozhong.zhang@intel.com> X-Mailer: git-send-email 2.10.1 In-Reply-To: <20170320000949.24675-1-haozhong.zhang@intel.com> References: <20170320000949.24675-1-haozhong.zhang@intel.com> Cc: Konrad Rzeszutek Wilk , Dan Williams , Andrew Cooper , Jan Beulich , Haozhong Zhang Subject: [Xen-devel] [RFC XEN PATCH v2 02/15] xen: probe pmem regions via ACPI NFIT X-BeenThere: xen-devel@lists.xen.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: xen-devel-bounces@lists.xen.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP Probe the address ranges of pmem regions via ACPI NFIT and report them to Xen hypervisor. Signed-off-by: Haozhong Zhang --- Cc: Jan Beulich Cc: Andrew Cooper --- xen/arch/x86/acpi/boot.c | 4 ++ xen/common/Makefile | 1 + xen/common/pmem.c | 106 ++++++++++++++++++++++++++++++++++++++++++ xen/drivers/acpi/Makefile | 2 + xen/drivers/acpi/nfit.c | 116 ++++++++++++++++++++++++++++++++++++++++++++++ xen/include/acpi/actbl.h | 1 + xen/include/acpi/actbl1.h | 42 +++++++++++++++++ xen/include/xen/acpi.h | 4 ++ xen/include/xen/pmem.h | 28 +++++++++++ 9 files changed, 304 insertions(+) create mode 100644 xen/common/pmem.c create mode 100644 xen/drivers/acpi/nfit.c create mode 100644 xen/include/xen/pmem.h diff --git a/xen/arch/x86/acpi/boot.c b/xen/arch/x86/acpi/boot.c index 33c9133812..83d73868d6 100644 --- a/xen/arch/x86/acpi/boot.c +++ b/xen/arch/x86/acpi/boot.c @@ -754,5 +754,9 @@ int __init acpi_boot_init(void) acpi_table_parse(ACPI_SIG_BGRT, acpi_invalidate_bgrt); +#ifdef CONFIG_PMEM + acpi_nfit_init(); +#endif + return 0; } diff --git a/xen/common/Makefile b/xen/common/Makefile index 0fed30bcc6..16c273b6d4 100644 --- a/xen/common/Makefile +++ b/xen/common/Makefile @@ -29,6 +29,7 @@ obj-y += notifier.o obj-y += page_alloc.o obj-$(CONFIG_HAS_PDX) += pdx.o obj-$(CONFIG_PERF_COUNTERS) += perfc.o +obj-$(CONFIG_PMEM) += pmem.o obj-y += preempt.o obj-y += random.o obj-y += rangeset.o diff --git a/xen/common/pmem.c b/xen/common/pmem.c new file mode 100644 index 0000000000..3c150cf1dd --- /dev/null +++ b/xen/common/pmem.c @@ -0,0 +1,106 @@ +/* + * xen/common/pmem.c + * + * Copyright (C) 2017, Intel Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms and conditions of the GNU General Public + * License, version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; If not, see . + */ + +#include +#include +#include +#include + +/* + * All pmem regions probed via SPA range structures of ACPI NFIT are + * linked in pmem_regions. + */ +static DEFINE_SPINLOCK(pmem_regions_lock); +static LIST_HEAD(pmem_regions); + +struct pmem { + struct list_head link; /* link to pmem_list */ + unsigned long smfn; /* start MFN of the whole pmem region */ + unsigned long emfn; /* end MFN of the whole pmem region */ +}; + +static bool check_overlap(unsigned long smfn1, unsigned long emfn1, + unsigned long smfn2, unsigned long emfn2) +{ + return smfn1 < emfn2 && smfn2 < emfn1; +} + +static struct pmem *alloc_pmem_struct(unsigned long smfn, unsigned long emfn) +{ + struct pmem *pmem = xzalloc(struct pmem); + + if ( !pmem ) + return NULL; + + pmem->smfn = smfn; + pmem->emfn = emfn; + + return pmem; +} + +static int pmem_list_add(struct list_head *list, struct pmem *entry) +{ + struct list_head *cur; + unsigned long smfn = entry->smfn, emfn = entry->emfn; + + list_for_each_prev(cur, list) + { + struct pmem *cur_pmem = list_entry(cur, struct pmem, link); + unsigned long cur_smfn = cur_pmem->smfn; + unsigned long cur_emfn = cur_pmem->emfn; + + if ( check_overlap(smfn, emfn, cur_smfn, cur_emfn) ) + return -EINVAL; + + if ( cur_smfn < smfn ) + break; + } + + list_add(&entry->link, cur); + + return 0; +} + +/** + * Register a pmem region to Xen. It's used by Xen hypervisor to collect + * all pmem regions can be used later. + * + * Parameters: + * smfn, emfn: start and end MFNs of the pmem region + * + * Return: + * On success, return 0. Otherwise, an error number is returned. + */ +int pmem_register(unsigned long smfn, unsigned long emfn) +{ + int rc; + struct pmem *pmem; + + if ( smfn >= emfn ) + return -EINVAL; + + pmem = alloc_pmem_struct(smfn, emfn); + if ( !pmem ) + return -ENOMEM; + + spin_lock(&pmem_regions_lock); + rc = pmem_list_add(&pmem_regions, pmem); + spin_unlock(&pmem_regions_lock); + + return rc; +} diff --git a/xen/drivers/acpi/Makefile b/xen/drivers/acpi/Makefile index 444b11d583..cef9d90222 100644 --- a/xen/drivers/acpi/Makefile +++ b/xen/drivers/acpi/Makefile @@ -9,3 +9,5 @@ obj-$(CONFIG_HAS_CPUFREQ) += pmstat.o obj-$(CONFIG_X86) += hwregs.o obj-$(CONFIG_X86) += reboot.o + +obj-$(CONFIG_PMEM) += nfit.o diff --git a/xen/drivers/acpi/nfit.c b/xen/drivers/acpi/nfit.c new file mode 100644 index 0000000000..ceac121dd2 --- /dev/null +++ b/xen/drivers/acpi/nfit.c @@ -0,0 +1,116 @@ +/* + * xen/drivers/acpi/nfit.c + * + * Copyright (C) 2017, Intel Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms and conditions of the GNU General Public + * License, version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; If not, see . + */ + +#include +#include +#include +#include +#include +#include + +static struct acpi_table_nfit *nfit __read_mostly = NULL; + +/* ACPI 6.1: GUID of a byte addressable persistent memory region */ +static const uint8_t nfit_spa_pmem_uuid[] = +{ + 0x79, 0xd3, 0xf0, 0x66, 0xf3, 0xb4, 0x74, 0x40, + 0xac, 0x43, 0x0d, 0x33, 0x18, 0xb7, 0x8c, 0xdb, +}; + +/** + * Enumerate each sub-table of NFIT. + * + * For a sub-table of type @type, @parse_cb() (if not NULL) is called + * to parse the sub-table. @parse_cb() returns 0 on success, and + * returns non-zero error code on errors. + * + * Parameters: + * nfit: NFIT + * type: the type of sub-table that will be parsed + * parse_cb: the function used to parse each sub-table + * arg: the argument passed to @parse_cb() + * + * Return: + * 0 on success, non-zero on failure + */ +static int acpi_nfit_foreach_subtable( + struct acpi_table_nfit *nfit, enum acpi_nfit_type type, + int (*parse_cb)(const struct acpi_nfit_header *, void *arg), void *arg) +{ + struct acpi_table_header *table = (struct acpi_table_header *)nfit; + struct acpi_nfit_header *hdr; + uint32_t hdr_offset = sizeof(*nfit); + int ret = 0; + + while ( hdr_offset < table->length ) + { + hdr = (void *)nfit + hdr_offset; + hdr_offset += hdr->length; + if ( hdr->type == type && parse_cb ) + { + ret = parse_cb(hdr, arg); + if ( ret ) + break; + } + } + + return ret; +} + +static int __init acpi_nfit_spa_probe_pmem(const struct acpi_nfit_header *hdr, + void *opaque) +{ + struct acpi_nfit_system_address *spa = + (struct acpi_nfit_system_address *)hdr; + unsigned long smfn = paddr_to_pfn(spa->address); + unsigned long emfn = paddr_to_pfn(spa->address + spa->length); + int rc; + + if ( memcmp(spa->range_guid, nfit_spa_pmem_uuid, 16) ) + return 0; + + rc = pmem_register(smfn, emfn); + if ( rc ) + printk(XENLOG_ERR + "NFIT: failed to add pmem mfns: 0x%lx - 0x%lx, err %d\n", + smfn, emfn, rc); + else + printk(XENLOG_INFO "NFIT: pmem mfn 0x%lx - 0x%lx\n", smfn, emfn); + + /* ignore the error and continue to add the next pmem range */ + return 0; +} + +void __init acpi_nfit_init(void) +{ + acpi_status status; + acpi_physical_address nfit_addr; + acpi_native_uint nfit_len; + + status = acpi_get_table_phys(ACPI_SIG_NFIT, 0, &nfit_addr, &nfit_len); + if ( ACPI_FAILURE(status) ) + return; + + map_pages_to_xen((unsigned long)__va(nfit_addr), PFN_DOWN(nfit_addr), + PFN_UP(nfit_addr + nfit_len) - PFN_DOWN(nfit_addr), + PAGE_HYPERVISOR); + nfit = (struct acpi_table_nfit *)__va(nfit_addr); + + acpi_nfit_foreach_subtable(nfit, ACPI_NFIT_TYPE_SYSTEM_ADDRESS, + acpi_nfit_spa_probe_pmem, NULL); +} diff --git a/xen/include/acpi/actbl.h b/xen/include/acpi/actbl.h index 3079176992..6e113b0873 100644 --- a/xen/include/acpi/actbl.h +++ b/xen/include/acpi/actbl.h @@ -71,6 +71,7 @@ #define ACPI_SIG_XSDT "XSDT" /* Extended System Description Table */ #define ACPI_SIG_SSDT "SSDT" /* Secondary System Description Table */ #define ACPI_RSDP_NAME "RSDP" /* Short name for RSDP, not signature */ +#define ACPI_SIG_NFIT "NFIT" /* NVDIMM Firmware Interface Table */ /* * All tables and structures must be byte-packed to match the ACPI diff --git a/xen/include/acpi/actbl1.h b/xen/include/acpi/actbl1.h index e1991362dc..a59ac11325 100644 --- a/xen/include/acpi/actbl1.h +++ b/xen/include/acpi/actbl1.h @@ -905,6 +905,48 @@ struct acpi_msct_proximity { /******************************************************************************* * + * NFIT - NVDIMM Interface Table (ACPI 6.0+) + * Version 1 + * + ******************************************************************************/ + +struct acpi_table_nfit { + struct acpi_table_header header; /* Common ACPI table header */ + u32 reserved; /* Reserved, must be zero */ +}; + +/* Subtable header for NFIT */ + +struct acpi_nfit_header { + u16 type; + u16 length; +}; + +/* Values for subtable type in struct acpi_nfit_header */ + +enum acpi_nfit_type { + ACPI_NFIT_TYPE_SYSTEM_ADDRESS = 0, +}; + +/* + * NFIT Subtables + */ + +/* type 0: System Physical Address Range Structure */ +struct acpi_nfit_system_address { + struct acpi_nfit_header header; + u16 range_index; + u16 flags; + u32 reserved; /* Reseved, must be zero */ + u32 proximity_domain; + u8 range_guid[16]; + u64 address; + u64 length; + u64 memory_mapping; +}; + +/******************************************************************************* + * * SBST - Smart Battery Specification Table * Version 1 * diff --git a/xen/include/xen/acpi.h b/xen/include/xen/acpi.h index 30ec0eec5f..8edb9a275e 100644 --- a/xen/include/xen/acpi.h +++ b/xen/include/xen/acpi.h @@ -180,4 +180,8 @@ void acpi_reboot(void); void acpi_dmar_zap(void); void acpi_dmar_reinstate(void); +#ifdef CONFIG_PMEM +void acpi_nfit_init(void); +#endif /* CONFIG_PMEM */ + #endif /*_LINUX_ACPI_H*/ diff --git a/xen/include/xen/pmem.h b/xen/include/xen/pmem.h new file mode 100644 index 0000000000..1144e86f98 --- /dev/null +++ b/xen/include/xen/pmem.h @@ -0,0 +1,28 @@ +/* + * xen/include/xen/pmem.h + * + * Copyright (C) 2017, Intel Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms and conditions of the GNU General Public + * License, version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; If not, see . + */ + +#ifndef __XEN_PMEM_H__ +#define __XEN_PMEM_H__ +#ifdef CONFIG_PMEM + +#include + +int pmem_register(unsigned long smfn, unsigned long emfn); + +#endif /* CONFIG_PMEM */ +#endif /* __XEN_PMEM_H__ */