From patchwork Thu Aug 6 03:32:47 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeremy Kerr X-Patchwork-Id: 504460 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.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id D6D3B1402BA for ; Thu, 6 Aug 2015 13:32:52 +1000 (AEST) Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 8346E1A0DC5 for ; Thu, 6 Aug 2015 13:32:52 +1000 (AEST) X-Original-To: skiboot@lists.ozlabs.org Delivered-To: skiboot@lists.ozlabs.org Received: from ozlabs.org (ozlabs.org [IPv6:2401:3900:2:1::2]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id CB22F1A0655 for ; Thu, 6 Aug 2015 13:32:48 +1000 (AEST) Received: by ozlabs.org (Postfix, from userid 1023) id B4A7E1402BA; Thu, 6 Aug 2015 13:32:48 +1000 (AEST) MIME-Version: 1.0 Message-Id: <1438831967.94433.255092909067.1.gpush@pudge> To: skiboot@lists.ozlabs.org From: Jeremy Kerr Date: Thu, 06 Aug 2015 11:32:47 +0800 Subject: [Skiboot] [PATCH] external/opal-prd: Only map each PRD range once X-BeenThere: skiboot@lists.ozlabs.org X-Mailman-Version: 2.1.20 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" Currently, opal-prd will create a new mapping (via mmap()) on every call to get_reserved_mem(). HBRT may end up calling this many times for the same range, which will consume virtual address space. There's no interface to unmap memory, so we may fail after too many calls. Instead, store the mapping in struct prd_range on first get_reserved_mem. Subsequent calls will re-use the same mapping. Signed-off-by: Jeremy Kerr --- external/opal-prd/opal-prd.c | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/external/opal-prd/opal-prd.c b/external/opal-prd/opal-prd.c index 9f686c5..82d9901 100644 --- a/external/opal-prd/opal-prd.c +++ b/external/opal-prd/opal-prd.c @@ -60,6 +60,7 @@ struct prd_range { const char *name; uint64_t physaddr; uint64_t size; + void *buf; }; struct opal_prd_ctx { @@ -275,9 +276,7 @@ int hservice_scom_write(uint64_t chip_id, uint64_t addr, uint64_t hservice_get_reserved_mem(const char *name) { - uint64_t align_physaddr, offset; struct prd_range *range; - void *addr; pr_debug("IMAGE: hservice_get_reserved_mem: %s", name); @@ -288,24 +287,35 @@ uint64_t hservice_get_reserved_mem(const char *name) return 0; } - pr_debug("IMAGE: Mapping 0x%016lx 0x%08lx %s", - range->physaddr, range->size, range->name); + if (!range->buf) { + uint64_t align_physaddr, offset; + + pr_debug("IMAGE: Mapping 0x%016lx 0x%08lx %s", + range->physaddr, range->size, range->name); - align_physaddr = range->physaddr & ~(ctx->page_size-1); - offset = range->physaddr & (ctx->page_size-1); - addr = mmap(NULL, range->size, PROT_WRITE | PROT_READ, - MAP_SHARED, ctx->fd, align_physaddr); + align_physaddr = range->physaddr & ~(ctx->page_size-1); + offset = range->physaddr & (ctx->page_size-1); + range->buf = mmap(NULL, range->size, PROT_WRITE | PROT_READ, + MAP_SHARED, ctx->fd, align_physaddr); - if (addr == MAP_FAILED) { - pr_log(LOG_ERR, "IMAGE: mmap of %s(0x%016lx) failed: %m", + if (range->buf == MAP_FAILED) + pr_log(LOG_ERR, + "IMAGE: mmap of %s(0x%016lx) failed: %m", name, range->physaddr); + else + range->buf += offset; + } + + if (range->buf == MAP_FAILED) { + pr_log(LOG_WARNING, "IMAGE: get_reserved_mem: %s has no vaddr", + name); return 0; } pr_debug("IMAGE: hservice_get_reserved_mem: %s(0x%016lx) address %p", - name, range->physaddr, addr); + name, range->physaddr, range->buf); - return (uint64_t)addr + offset; + return (uint64_t)range->buf; } void hservice_nanosleep(uint64_t i_seconds, uint64_t i_nano_seconds) @@ -823,6 +833,7 @@ static int prd_init_one_range(struct opal_prd_ctx *ctx, const char *path, range->name = strndup(label, label_len); range->physaddr = be64toh(reg[0]); range->size = be64toh(reg[1]); + range->buf = NULL; rc = 0; out_free: