From patchwork Mon Sep 11 04:37:47 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Haozhong Zhang X-Patchwork-Id: 9946577 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 6A8686035D for ; Mon, 11 Sep 2017 04:41:40 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 60509289DE for ; Mon, 11 Sep 2017 04:41:40 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 552E628AD7; Mon, 11 Sep 2017 04:41:40 +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, RCVD_IN_DNSWL_MED 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 B4B97289DE for ; Mon, 11 Sep 2017 04:41:39 +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 1drGUt-0001CD-Vn; Mon, 11 Sep 2017 04:38:59 +0000 Received: from mail6.bemta6.messagelabs.com ([193.109.254.103]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1drGUt-0001B8-8d for xen-devel@lists.xen.org; Mon, 11 Sep 2017 04:38:59 +0000 Received: from [193.109.254.147] by server-10.bemta-6.messagelabs.com id 66/98-03642-26316B95; Mon, 11 Sep 2017 04:38:58 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFvrFLMWRWlGSWpSXmKPExsXS1tYhopsovC3 S4Mk2a4slHxezODB6HN39mymAMYo1My8pvyKBNWPdsY1MBU8cKh617WRuYPxs2MXIySEkMJ1R YuEmFhBbQoBX4siyGawQdoDEvQ3HgGwuoJpeRokn0xeCJdgE9CVWPD4IZosISEtc+3yZEcRmF mhgknj7twjEFhbwlHhybCYTiM0ioCrx+nAXWA2vgK3EnC3b2CAWyEvsarsINodTwE7i4Mt3zB AH2UosOL2AdQIj7wJGhlWMGsWpRWWpRbpG5npJRZnpGSW5iZk5uoYGZnq5qcXFiempOYlJxXr J+bmbGIHhwAAEOxgXrw08xCjJwaQkyvvu+JZIIb6k/JTKjMTijPii0pzU4kOMMhwcShK8ZwS3 RQoJFqWmp1akZeYAAxMmLcHBoyTCuwgkzVtckJhbnJkOkTrFqMvRcfPuHyYhlrz8vFQpcd7NI EUCIEUZpXlwI2BRcolRVkqYlxHoKCGegtSi3MwSVPlXjOIcjErCvDJCQFN4MvNK4Da9AjqCCe gInktbQI4oSURISTUwakT2rs++bNjFr+29T1DE8Trr3siuHN+vGpNDpKdN/Db5CM8p0ymZzv/ izzLnWFf9mn81jFOgV0edR+bfg1s3J1pMVFnS/Z/J7/w9hduLp79+XXE2/e7sCfKPVGvlbnI+ cbi92orV4Gvgm8PCTlftGfua5v2cerTP3uzWy0nJ/1m4f64oPZ0mosRSnJFoqMVcVJwIAOvKi zCNAgAA X-Env-Sender: haozhong.zhang@intel.com X-Msg-Ref: server-2.tower-27.messagelabs.com!1505104735!56506342!1 X-Originating-IP: [134.134.136.20] X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: VHJ1c3RlZCBJUDogMTM0LjEzNC4xMzYuMjAgPT4gMzU1MzU4\n X-StarScan-Received: X-StarScan-Version: 9.4.45; banners=-,-,- X-VirusChecked: Checked Received: (qmail 47598 invoked from network); 11 Sep 2017 04:38:57 -0000 Received: from mga02.intel.com (HELO mga02.intel.com) (134.134.136.20) by server-2.tower-27.messagelabs.com with DHE-RSA-AES256-GCM-SHA384 encrypted SMTP; 11 Sep 2017 04:38:57 -0000 Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 10 Sep 2017 21:38:55 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos; i="5.42,376,1500966000"; d="scan'208"; a="1217078281" Received: from hz-desktop.sh.intel.com (HELO localhost) ([10.239.159.142]) by fmsmga002.fm.intel.com with ESMTP; 10 Sep 2017 21:38:53 -0700 From: Haozhong Zhang To: xen-devel@lists.xen.org Date: Mon, 11 Sep 2017 12:37:47 +0800 Message-Id: <20170911043820.14617-7-haozhong.zhang@intel.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170911043820.14617-1-haozhong.zhang@intel.com> References: <20170911043820.14617-1-haozhong.zhang@intel.com> Cc: Haozhong Zhang , Andrew Cooper , Jan Beulich , Chao Peng , Dan Williams Subject: [Xen-devel] [RFC XEN PATCH v3 06/39] acpi: probe valid PMEM regions via 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 A PMEM region with failures (e.g., not properly flushed in the last power cycle, or some blocks within it are borken) cannot be safely used by Xen and guest. Scan the state flags of NVDIMM region mapping structures in NFIT to check whether any failures happened to a PMEM region. The recovery of those failure are left out of Xen (e.g. left to the firmware or other management utilities on the bare metal). Signed-off-by: Haozhong Zhang --- Cc: Jan Beulich Cc: Andrew Cooper --- xen/arch/x86/acpi/boot.c | 4 ++ xen/drivers/acpi/nfit.c | 153 +++++++++++++++++++++++++++++++++++++++++++++- xen/include/acpi/actbl1.h | 26 ++++++++ xen/include/xen/acpi.h | 1 + 4 files changed, 183 insertions(+), 1 deletion(-) diff --git a/xen/arch/x86/acpi/boot.c b/xen/arch/x86/acpi/boot.c index 8e6c96dcf6..f52a2c6dc5 100644 --- a/xen/arch/x86/acpi/boot.c +++ b/xen/arch/x86/acpi/boot.c @@ -732,5 +732,9 @@ int __init acpi_boot_init(void) acpi_table_parse(ACPI_SIG_BGRT, acpi_invalidate_bgrt); +#ifdef CONFIG_NVDIMM_PMEM + acpi_nfit_init(); +#endif + return 0; } diff --git a/xen/drivers/acpi/nfit.c b/xen/drivers/acpi/nfit.c index e099378ee0..b88a587b8d 100644 --- a/xen/drivers/acpi/nfit.c +++ b/xen/drivers/acpi/nfit.c @@ -31,11 +31,143 @@ static const uint8_t nfit_spa_pmem_guid[] = 0xac, 0x43, 0x0d, 0x33, 0x18, 0xb7, 0x8c, 0xdb, }; +struct nfit_spa_desc { + struct list_head link; + struct acpi_nfit_system_address *acpi_table; +}; + +struct nfit_memdev_desc { + struct list_head link; + struct acpi_nfit_memory_map *acpi_table; + struct nfit_spa_desc *spa_desc; +}; + struct acpi_nfit_desc { struct acpi_table_nfit *acpi_table; + struct list_head spa_list; + struct list_head memdev_list; }; -static struct acpi_nfit_desc nfit_desc; +static struct acpi_nfit_desc nfit_desc = { + .spa_list = LIST_HEAD_INIT(nfit_desc.spa_list), + .memdev_list = LIST_HEAD_INIT(nfit_desc.memdev_list), +}; + +static void __init acpi_nfit_del_subtables(struct acpi_nfit_desc *desc) +{ + struct nfit_spa_desc *spa, *spa_next; + struct nfit_memdev_desc *memdev, *memdev_next; + + list_for_each_entry_safe(spa, spa_next, &desc->spa_list, link) + { + list_del(&spa->link); + xfree(spa); + } + list_for_each_entry_safe (memdev, memdev_next, &desc->memdev_list, link) + { + list_del(&memdev->link); + xfree(memdev); + } +} + +static int __init acpi_nfit_add_subtables(struct acpi_nfit_desc *desc) +{ + struct acpi_table_nfit *nfit_table = desc->acpi_table; + uint32_t hdr_offset = sizeof(*nfit_table); + uint32_t nfit_length = nfit_table->header.length; + struct acpi_nfit_header *hdr; + struct nfit_spa_desc *spa_desc; + struct nfit_memdev_desc *memdev_desc; + int ret = 0; + +#define INIT_DESC(desc, acpi_hdr, acpi_type, desc_list) \ + do { \ + (desc) = xzalloc(typeof(*(desc))); \ + if ( unlikely(!(desc)) ) { \ + ret = -ENOMEM; \ + goto nomem; \ + } \ + (desc)->acpi_table = (acpi_type *)(acpi_hdr); \ + INIT_LIST_HEAD(&(desc)->link); \ + list_add_tail(&(desc)->link, (desc_list)); \ + } while ( 0 ) + + while ( hdr_offset < nfit_length ) + { + hdr = (void *)nfit_table + hdr_offset; + hdr_offset += hdr->length; + + switch ( hdr->type ) + { + case ACPI_NFIT_TYPE_SYSTEM_ADDRESS: + INIT_DESC(spa_desc, hdr, struct acpi_nfit_system_address, + &desc->spa_list); + break; + + case ACPI_NFIT_TYPE_MEMORY_MAP: + INIT_DESC(memdev_desc, hdr, struct acpi_nfit_memory_map, + &desc->memdev_list); + break; + + default: + continue; + } + } + +#undef INIT_DESC + + return 0; + + nomem: + acpi_nfit_del_subtables(desc); + + return ret; +} + +static void __init acpi_nfit_link_subtables(struct acpi_nfit_desc *desc) +{ + struct nfit_spa_desc *spa_desc; + struct nfit_memdev_desc *memdev_desc; + uint16_t spa_idx; + + list_for_each_entry(memdev_desc, &desc->memdev_list, link) + { + spa_idx = memdev_desc->acpi_table->range_index; + list_for_each_entry(spa_desc, &desc->spa_list, link) + { + if ( spa_desc->acpi_table->range_index == spa_idx ) + break; + } + memdev_desc->spa_desc = spa_desc; + } +} + +static void __init acpi_nfit_register_pmem(struct acpi_nfit_desc *desc) +{ + struct nfit_spa_desc *spa_desc; + struct nfit_memdev_desc *memdev_desc; + struct acpi_nfit_system_address *spa; + unsigned long smfn, emfn; + + list_for_each_entry(memdev_desc, &desc->memdev_list, link) + { + spa_desc = memdev_desc->spa_desc; + + if ( !spa_desc || + (memdev_desc->acpi_table->flags & + (ACPI_NFIT_MEM_SAVE_FAILED | ACPI_NFIT_MEM_RESTORE_FAILED | + ACPI_NFIT_MEM_FLUSH_FAILED | ACPI_NFIT_MEM_NOT_ARMED | + ACPI_NFIT_MEM_MAP_FAILED)) ) + continue; + + spa = spa_desc->acpi_table; + if ( memcmp(spa->range_guid, nfit_spa_pmem_guid, 16) ) + continue; + smfn = paddr_to_pfn(spa->address); + emfn = paddr_to_pfn(spa->address + spa->length); + printk(XENLOG_INFO "NFIT: PMEM MFNs 0x%lx - 0x%lx\n", smfn, emfn); + } +} void __init acpi_nfit_boot_init(void) { @@ -53,6 +185,25 @@ void __init acpi_nfit_boot_init(void) PAGE_HYPERVISOR); } +void __init acpi_nfit_init(void) +{ + if ( !nfit_desc.acpi_table ) + return; + + /* Collect all SPA and memory map sub-tables. */ + if ( acpi_nfit_add_subtables(&nfit_desc) ) + { + printk(XENLOG_ERR "NFIT: no memory for NFIT management\n"); + return; + } + + /* Link descriptors of SPA and memory map sub-tables. */ + acpi_nfit_link_subtables(&nfit_desc); + + /* Register valid pmem regions to Xen hypervisor. */ + acpi_nfit_register_pmem(&nfit_desc); +} + /** * Search pmem regions overlapped with the specified address range. * diff --git a/xen/include/acpi/actbl1.h b/xen/include/acpi/actbl1.h index 94d8d7775c..037652916a 100644 --- a/xen/include/acpi/actbl1.h +++ b/xen/include/acpi/actbl1.h @@ -946,6 +946,32 @@ struct acpi_nfit_system_address { u64 memory_mapping; }; +/* 1: Memory Device to System Address Range Map Structure */ +struct acpi_nfit_memory_map { + struct acpi_nfit_header header; + u32 device_handle; + u16 physical_id; + u16 region_id; + u16 range_index; + u16 region_index; + u64 region_size; + u64 region_offset; + u64 address; + u16 interleave_index; + u16 interleave_ways; + u16 flags; + u16 reserved; /* Reserved, must be zero */ +}; + +/* Flags in struct acpi_nfit_memory_map */ +#define ACPI_NFIT_MEM_SAVE_FAILED (1) /* 00: Last SAVE to Memory Device failed */ +#define ACPI_NFIT_MEM_RESTORE_FAILED (1<<1) /* 01: Last RESTORE from Memory Device failed */ +#define ACPI_NFIT_MEM_FLUSH_FAILED (1<<2) /* 02: Platform flush failed */ +#define ACPI_NFIT_MEM_NOT_ARMED (1<<3) /* 03: Memory Device is not armed */ +#define ACPI_NFIT_MEM_HEALTH_OBSERVED (1<<4) /* 04: Memory Device observed SMART/health events */ +#define ACPI_NFIT_MEM_HEALTH_ENABLED (1<<5) /* 05: SMART/health events enabled */ +#define ACPI_NFIT_MEM_MAP_FAILED (1<<6) /* 06: Mapping to SPA failed */ + /******************************************************************************* * * SBST - Smart Battery Specification Table diff --git a/xen/include/xen/acpi.h b/xen/include/xen/acpi.h index 1bd8f9f4e4..088f01255d 100644 --- a/xen/include/xen/acpi.h +++ b/xen/include/xen/acpi.h @@ -185,6 +185,7 @@ void acpi_nfit_boot_init(void); bool acpi_nfit_boot_search_pmem(unsigned long smfn, unsigned long emfn, unsigned long *ret_smfn, unsigned long *ret_emfn); +void acpi_nfit_init(void); #endif /* CONFIG_NVDIMM_PMEM */ #endif /*_LINUX_ACPI_H*/