From patchwork Tue Feb 19 07:53:39 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oliver O'Halloran X-Patchwork-Id: 1044528 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 443Y190XZ9z9s7h for ; Tue, 19 Feb 2019 18:54:53 +1100 (AEDT) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="tldjEf6h"; dkim-atps=neutral Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 443Y185V3vzDqJK for ; Tue, 19 Feb 2019 18:54:52 +1100 (AEDT) X-Original-To: skiboot@lists.ozlabs.org Delivered-To: skiboot@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gmail.com (client-ip=2607:f8b0:4864:20::643; helo=mail-pl1-x643.google.com; envelope-from=oohall@gmail.com; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="tldjEf6h"; dkim-atps=neutral Received: from mail-pl1-x643.google.com (mail-pl1-x643.google.com [IPv6:2607:f8b0:4864:20::643]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 443Y086sfpzDqKD for ; Tue, 19 Feb 2019 18:54:00 +1100 (AEDT) Received: by mail-pl1-x643.google.com with SMTP id q3so2656135pll.4 for ; Mon, 18 Feb 2019 23:54:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=1qcU6I6wnO0b+U7lvxqpqiJ3i0UXLHBh+5YF0XksDM4=; b=tldjEf6hnFAopgRnTYk7pLAZZbqI5Jr06ZimBThx7UllG6Fys0rrRHDiraTUoX7PN0 Dis3Rm8b+nPD1/VgAPMlDNIOjvhYm54oe5JVN2wY1i9aELWwez5eZprZtIx6srayIT6A cAdni78Zc/ziwHhdZAc4WXAW+vka4N49PIlFhzQlB4+OVqtczxWfhWcwog8rlHLK30mI kNEBUEhQDfH5O5rDCv6vrT0ZVSHdr5mnlXQE77z90VjMa02qrUd4Xkd1fzBDQmyELZHv UiYDAhg6zY8ZYuxJzQVVouKuznSORTLJnql2AKS9bIkmQganm2/GIYXar5OCesZCU880 7PkQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=1qcU6I6wnO0b+U7lvxqpqiJ3i0UXLHBh+5YF0XksDM4=; b=X0bKQPYNpxFiYEnEv7PqR6GHNhS87t4OrjNS3YwVK4QOTXHMSAdNLOQaC2Z0C7ETsM YXNz6wQfqFanomNZaXATaRErvrMF+M9z5kSrEt1/BxUPo3Nv2Dyzk8mDhtVFiWjqDyA1 ySW1YyUrGXVl+qCFYrUqb13B/jLzD2mI1imWTPStW1z1oz7B1njm0EpUN373NBsFiQxv zGJvr/6QxAx2V6w0LImLYja4YcvFha92QaLTVofyPpvl1bsOWZtkwzVuj9zCBRm/UaEw +MCdncRn8iHIGINcWZgRAzaXMWXppoUxevnU+y15rzFKwdIUkK1cMljO1yY+SJzT8Zux Rw9g== X-Gm-Message-State: AHQUAuYWihz+xqXHAUEVlbcYej/6SQjxbNRH5iPWI7trOWo5Hz6kODdm juqmWN4J3x6oR32pzZJklPcjquCV X-Google-Smtp-Source: AHgI3IZvDJc5v9w1I8RXjQ0Wm3qr9YAmtCRbEKQ/XEDkoTqWfo69ZpwBQ/s0SgoW2iM+1sddlzM54A== X-Received: by 2002:a17:902:6b03:: with SMTP id o3mr29619501plk.126.1550562839001; Mon, 18 Feb 2019 23:53:59 -0800 (PST) Received: from wafer.ozlabs.ibm.com ([122.99.82.10]) by smtp.gmail.com with ESMTPSA id r3sm39651582pgn.48.2019.02.18.23.53.57 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 18 Feb 2019 23:53:58 -0800 (PST) From: Oliver O'Halloran To: skiboot@lists.ozlabs.org Date: Tue, 19 Feb 2019 18:53:39 +1100 Message-Id: <20190219075339.14226-4-oohall@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190219075339.14226-1-oohall@gmail.com> References: <20190219075339.14226-1-oohall@gmail.com> MIME-Version: 1.0 Subject: [Skiboot] [PATCH 4/4] hdata/memory: Add NVDIMM support X-BeenThere: skiboot@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Mailing list for skiboot development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Skiboot" NVDIMMs are memory modules that use a battery backup system to allow the contents RAM to be saved to non-volatile storage if system power goes away unexpectedly. This allows them to be used a high-performance storage device, suitable for serving as a cache for SSDs and the like. Configuration of NVDIMMs is handled by hostboot and communicated to OPAL via the HDAT. We need to parse out the NVDIMM memory ranges and create memory regions with the "pmem-region" compatible label to make them available to the host. Signed-off-by: Oliver O'Halloran --- hdata/memory.c | 110 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 100 insertions(+), 10 deletions(-) diff --git a/hdata/memory.c b/hdata/memory.c index 3e6271444ce6..1ac03c137dbd 100644 --- a/hdata/memory.c +++ b/hdata/memory.c @@ -48,7 +48,25 @@ struct HDIF_ms_area_address_range { __be32 mirror_attr; __be64 mirror_start; __be32 controller_id; + __be32 phys_attr; } __packed; +#define PHYS_ATTR_TYPE_MASK 0xff000000 +#define PHYS_ATTR_TYPE_STD 0 +#define PHYS_ATTR_TYPE_NVDIMM 1 +#define PHYS_ATTR_TYPE_MRAM 2 +#define PHYS_ATTR_TYPE_PCM 3 + +#define PHYS_ATTR_STATUS_MASK 0x00ff0000 +/* + * The values here are mutually exclusive. I have no idea why anyone + * decided encoding these are flags rather than sequential numbers was + * a good idea, but here we are. + */ +#define PHYS_ATTR_STATUS_CANT_SAVE 0x01 +#define PHYS_ATTR_STATUS_SAVE_FAILED 0x02 +#define PHYS_ATTR_STATUS_SAVED 0x04 +#define PHYS_ATTR_STATUS_NOT_SAVED 0x08 +#define PHYS_ATTR_STATUS_MEM_INVALID 0xff #define MS_CONTROLLER_MCBIST_ID(id) GETFIELD(PPC_BITMASK32(0, 1), id) #define MS_CONTROLLER_MCS_ID(id) GETFIELD(PPC_BITMASK32(4, 7), id) @@ -92,42 +110,99 @@ static void append_chip_id(struct dt_node *mem, u32 id) p[len] = cpu_to_be32(id); } +static void update_status(struct dt_node *mem, uint32_t status) +{ + switch (status) { + case PHYS_ATTR_STATUS_CANT_SAVE: + if (!dt_find_property(mem, "save-trigged-unarmed")) + dt_add_property(mem, "save-trigger-unarmed", NULL, 0); + break; + + case PHYS_ATTR_STATUS_SAVE_FAILED: + if (!dt_find_property(mem, "save-failed")) + dt_add_property(mem, "save-failed", NULL, 0); + + break; + + case PHYS_ATTR_STATUS_MEM_INVALID: + if (dt_find_property(mem, "save-trigged-unarmed")) + dt_add_property_string(mem, "status", + "disabled-memory-invalid"); + break; + } +} + static bool add_address_range(struct dt_node *root, const struct HDIF_ms_area_id *id, - const struct HDIF_ms_area_address_range *arange) + const struct HDIF_ms_area_address_range *arange, + uint32_t mem_type, uint32_t mem_status) { + const char *compat = NULL, *dev_type = NULL, *name = NULL; struct dt_node *mem; - u32 chip_id, type; + u32 chip_id; u64 reg[2]; chip_id = pcid_to_chip_id(be32_to_cpu(arange->chip)); prlog(PR_DEBUG, " Range: 0x%016llx..0x%016llx " - "on Chip 0x%x mattr: 0x%x\n", + "on Chip 0x%x mattr: 0x%x pattr: 0x%x status:0x%x\n", (long long)be64_to_cpu(arange->start), (long long)be64_to_cpu(arange->end), - chip_id, arange->mirror_attr); + chip_id, arange->mirror_attr, mem_type, mem_status); /* reg contains start and length */ reg[0] = cleanup_addr(be64_to_cpu(arange->start)); reg[1] = cleanup_addr(be64_to_cpu(arange->end)) - reg[0]; + switch (mem_type) { + case PHYS_ATTR_TYPE_STD: + name = "memory"; + dev_type = "memory"; + break; + + case PHYS_ATTR_TYPE_NVDIMM: + case PHYS_ATTR_TYPE_MRAM: + case PHYS_ATTR_TYPE_PCM: + /* fall through */ + name = "nvdimm"; + compat = "pmem-region"; + break; + + /* + * Future memory types could be volatile or non-volatile. Bail if don't + * recognise the type so we don't end up trashing data accidently. + */ + default: + return false; + } + if (be16_to_cpu(id->flags) & MS_AREA_SHARED) { - mem = dt_find_by_name_addr("memory", reg[0]); + mem = dt_find_by_name_addr(dt_root, name, reg[0]); if (mem) { append_chip_id(mem, chip_id); + if (mem_type == PHYS_ATTR_TYPE_NVDIMM) + update_status(mem, mem_status); return true; } } mem = dt_new_addr(root, name, reg[0]); - dt_add_property_string(mem, "device_type", "memory"); - dt_add_property_cells(mem, "ibm,chip-id", chip_id); + if (compat) + dt_add_property_string(mem, "compatible", compat); + if (dev_type) + dt_add_property_string(mem, "device_type", dev_type); + + /* add in the nvdimm backup status flags */ + if (mem_type == PHYS_ATTR_TYPE_NVDIMM) + update_status(mem, mem_status); + + /* common properties */ + dt_add_property_u64s(mem, "reg", reg[0], reg[1]); + dt_add_property_cells(mem, "ibm,chip-id", chip_id); if (be16_to_cpu(id->flags) & MS_AREA_SHARED) dt_add_property_cells(mem, DT_PRIVATE "share-id", be16_to_cpu(id->share_id)); - return true; } @@ -515,12 +590,27 @@ static void get_msareas(struct dt_node *root, /* This offset is from the arr, not the header! */ arange = (void *)arr + be32_to_cpu(arr->offset); for (j = 0; j < be32_to_cpu(arr->ecnt); j++) { + uint32_t type = 0, status = 0; + + /* + * Check that the required fields are present in this + * version of the HDAT structure. + */ offset = offsetof(struct HDIF_ms_area_address_range, controller_id); if (be32_to_cpu(arr->eactsz) >= offset) add_memory_controller(msarea, arange); - if (!add_address_range(root, id, arange)) - return; + offset = offsetof(struct HDIF_ms_area_address_range, phys_attr); + if (be32_to_cpu(arr->eactsz) >= offset) { + uint32_t attr = be32_to_cpu(arange->phys_attr); + + type = GETFIELD(PHYS_ATTR_TYPE_MASK, attr); + status = GETFIELD(PHYS_ATTR_STATUS_MASK, attr); + } + + if (add_address_range(root, id, arange, type, status)) + prerror("Unable to use memory range %d from MSAREA %d\n", j, i); + arange = (void *)arange + be32_to_cpu(arr->esize); } }