From patchwork Sat May 2 11:36:42 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicholas Piggin X-Patchwork-Id: 1281666 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [203.11.71.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 49Dq9M4y38z9sRf for ; Sat, 2 May 2020 23:05:27 +1000 (AEST) 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.a=rsa-sha256 header.s=20161025 header.b=RZVuIFfM; dkim-atps=neutral Received: from bilbo.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 49Dq9M47L8zDqpJ for ; Sat, 2 May 2020 23:05:27 +1000 (AEST) X-Original-To: skiboot@lists.ozlabs.org Delivered-To: skiboot@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gmail.com (client-ip=2607:f8b0:4864:20::1044; helo=mail-pj1-x1044.google.com; envelope-from=npiggin@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.a=rsa-sha256 header.s=20161025 header.b=RZVuIFfM; dkim-atps=neutral Received: from mail-pj1-x1044.google.com (mail-pj1-x1044.google.com [IPv6:2607:f8b0:4864:20::1044]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 49DnD122RxzDqXX for ; Sat, 2 May 2020 21:37:37 +1000 (AEST) Received: by mail-pj1-x1044.google.com with SMTP id hi11so1172024pjb.3 for ; Sat, 02 May 2020 04:37:36 -0700 (PDT) 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=NHVEXHPClpU9a1Q3zo+wN2H8+/Ug5/QPoqZTGDgy86M=; b=RZVuIFfMy8wmuujaa3UqcMIfmQ3Sp9W1QXKnBkFB6kcdLhQLzAoW0/+drFaLWsF6N7 Av6+AlVabcrwu0mpurRVQwBSOoYMCNwfixoI9C8TMwOnHW8OdFSezs14GbJtKu9dKf6y n45p3oPw60hQBWyUZ8+XVB1xZqvHN/+dQ2N1FAffPOLSMamtEf3DfouBg/kxxl8FbS+e gZ/DZqbniGOucpexKXyTBppjswwKK5kMs0v2wxm+gXA1ZKXfvG71ZmJ7hRcf5KL4vbrq aCn2IBhOws3jpHve/kuuAwR6LNKppGfg9GcfR0D14YBU3mkpBCpkNKioI0NUd4KWGt8G ka5g== 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=NHVEXHPClpU9a1Q3zo+wN2H8+/Ug5/QPoqZTGDgy86M=; b=JSo8DLap89Spz/jxO2NFXBxqvXFmIyAiBTH2264UXYnWhI5z89sJh6ATaZVMnOTad7 LsZg74r8OgWTiuAogHEgISV9gdSuevmyyNM9VokWBCwN0n1XHgiC1KuCPZRbq8zLDZZm XDu7j8np9R8H6D9uzuE8RLnqLqjekA0QKNjVaDqJGlWwlAAvNe9+qqmghVN6nVypY+tn I9SoMd7WJ+ozc260uCf3jAEeuzq0QNQmGH/vg7p+95sffoBcmPfnEVHrKu+f/dFWjCyy vdKpcKO8oXd/JlgLTymBkLbkWwmdHWdQbSeXsap3Hh8krJUuPM0Oy8iOtkqJHfRikKCw TJow== X-Gm-Message-State: AGi0PuZ6etNyEDiA7EkPpaQKToGniRhAdqomY5qlT8jhUoaEFkgT68xj 7IqgUznmAIEZaVGWRiWT+1zqtlY2 X-Google-Smtp-Source: APiQypIwkJOX7GTpJofDg+vzN6N7UaGtiuEaNY+Sj20Nxu1odTXOjgzOlAjoc6jMSsE1EoHfrhkoUQ== X-Received: by 2002:a17:90a:33c5:: with SMTP id n63mr5128149pjb.4.1588419454658; Sat, 02 May 2020 04:37:34 -0700 (PDT) Received: from bobo.ozlabs.ibm.com ([203.220.177.17]) by smtp.gmail.com with ESMTPSA id e135sm4367513pfh.37.2020.05.02.04.37.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 02 May 2020 04:37:34 -0700 (PDT) From: Nicholas Piggin To: skiboot@lists.ozlabs.org Date: Sat, 2 May 2020 21:36:42 +1000 Message-Id: <20200502113649.176329-3-npiggin@gmail.com> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20200502113649.176329-1-npiggin@gmail.com> References: <20200502113649.176329-1-npiggin@gmail.com> MIME-Version: 1.0 Subject: [Skiboot] [RFC PATCH 2/9] Add OPAL_SYM_TO_ADDR and OPAL_ADDR_TO_SYM 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" These calls can be used by Linux to annotate BUG addresses with symbols, look up symbol addresses in xmon, etc. This is preferable over having Linux parse the OPAL symbol map itself, because OPAL's parsing code already exists for its own symbol printing, and it can support other code regions than the skiboot symbols, e.g., the wake-up code in the HOMER (where CPUs have been seen to get stuck). Signed-off-by: Nicholas Piggin --- core/opal.c | 2 + core/utils.c | 102 ++++++++++++++++++++++-- doc/opal-api/opal-get-symbol-181.rst | 42 ++++++++++ doc/opal-api/opal-lookup-symbol-182.rst | 35 ++++++++ include/opal-api.h | 4 +- 5 files changed, 177 insertions(+), 8 deletions(-) create mode 100644 doc/opal-api/opal-get-symbol-181.rst create mode 100644 doc/opal-api/opal-lookup-symbol-182.rst diff --git a/core/opal.c b/core/opal.c index 97b5f89a8..864c244cc 100644 --- a/core/opal.c +++ b/core/opal.c @@ -162,6 +162,8 @@ int64_t opal_entry_check(struct stack_frame *eframe) case OPAL_CEC_REBOOT: case OPAL_CEC_REBOOT2: case OPAL_SIGNAL_SYSTEM_RESET: + case OPAL_ADDR_TO_SYM: + case OPAL_SYM_TO_ADDR: break; default: printf("CPU ATTEMPT TO RE-ENTER FIRMWARE! PIR=%04lx cpu @%p -> pir=%04x token=%llu\n", diff --git a/core/utils.c b/core/utils.c index d778fcdff..d53bcf374 100644 --- a/core/utils.c +++ b/core/utils.c @@ -52,40 +52,128 @@ char __attrconst tohex(uint8_t nibble) return __tohex[nibble]; } -static unsigned long get_symbol(unsigned long addr, char **sym, char **sym_end) +static unsigned long addr_to_sym(unsigned long addr, char **sym, char **sym_end, unsigned long *size) { - unsigned long prev = 0, next; + unsigned long prev = 0, next = 0; char *psym = NULL, *p = __sym_map_start; *sym = *sym_end = NULL; - while(p < __sym_map_end) { + + while (p < __sym_map_end) { next = strtoul(p, &p, 16) | SKIBOOT_BASE; if (next > addr && prev <= addr) { - p = psym + 3;; + if (!psym) + return 0; + p = psym + 3; if (p >= __sym_map_end) return 0; *sym = p; - while(p < __sym_map_end && *p != 10) + while (p < __sym_map_end && *p != '\n') p++; *sym_end = p; + *size = next - prev; + return prev; } + prev = next; psym = p; - while(p < __sym_map_end && *p != 10) + while (p < __sym_map_end && *p != '\n') + p++; + p++; + } + + return 0; +} + +static unsigned long sym_to_addr(const char *name, unsigned long *size) +{ + size_t len = strlen(name); + unsigned long addr = 0; + char *sym; + char *p = __sym_map_start; + + while (p < __sym_map_end) { + addr = strtoul(p, &p, 16) | SKIBOOT_BASE; + p += 3; + if (p >= __sym_map_end) + return 0; + + if (*(p + len) == '\n' && !strncmp(name, p, len)) { + char *sym_end; + + /* Now get the size */ + if (addr_to_sym(addr, &sym, &sym_end, size) == 0) { + if (strcmp(name, "_end")) + printf("sym_to_addr: name=%s p=%p addr=%lx addr_to_sym failed\n", name, p, addr); + *size = 0; + } + + /* + * May be more than one symbol at this address but + * symbol length calculation should still work in + * that case. + */ + + return addr; + } + + while (p < __sym_map_end && *p != '\n') p++; p++; } return 0; } +static int64_t opal_addr_to_sym(uint64_t addr, __be64 *symaddr, __be64 *symsize, char *namebuf, uint64_t buflen) +{ + unsigned long saddr; + unsigned long ssize; + char *sym, *sym_end; + size_t l; + + saddr = addr_to_sym(addr, &sym, &sym_end, &ssize); + if (!saddr) + return OPAL_RESOURCE; + + if (buflen > sym_end - sym) + l = sym_end - sym; + else + l = buflen - 1; + memcpy(namebuf, sym, l); + namebuf[l] = '\0'; + + *symaddr = cpu_to_be64(saddr); + *symsize = cpu_to_be64(ssize); + + return OPAL_SUCCESS; +} +opal_call(OPAL_ADDR_TO_SYM, opal_addr_to_sym, 5); + +static int64_t opal_sym_to_addr(const char *name, __be64 *symaddr, __be64 *symsize) +{ + unsigned long saddr; + unsigned long ssize; + + saddr = sym_to_addr(name, &ssize); + if (!saddr) + return OPAL_RESOURCE; + + *symaddr = cpu_to_be64(saddr); + *symsize = cpu_to_be64(ssize); + + return OPAL_SUCCESS; +} +opal_call(OPAL_SYM_TO_ADDR, opal_sym_to_addr, 3); + size_t snprintf_symbol(char *buf, size_t len, uint64_t addr) { unsigned long saddr; + unsigned long ssize; char *sym, *sym_end; size_t l; - saddr = get_symbol(addr, &sym, &sym_end); + saddr = addr_to_sym(addr, &sym, &sym_end, &ssize); if (!saddr) return 0; diff --git a/doc/opal-api/opal-get-symbol-181.rst b/doc/opal-api/opal-get-symbol-181.rst new file mode 100644 index 000000000..00ff18431 --- /dev/null +++ b/doc/opal-api/opal-get-symbol-181.rst @@ -0,0 +1,42 @@ +.. _OPAL_ADDR_TO_SYM: + +OPAL_ADDR_TO_SYM +================ + +.. code-block:: c + + #define OPAL_ADDR_TO_SYM 181 + + static int64_t opal_addr_to_sym(uint64_t addr, __be64 *symaddr, __be64 *symsize, char *namebuf, uint64_t buflen); + +This OPAL call looks up a firmware code address for symbol information. + +Arguments +--------- + + ``addr`` + Contains address to be looked up. + + ``symaddr`` + Returns the start address of the symbol for the object which + contains addr or immediately precedes addr. + + ``symsize`` + Returns the size of the object, or the number of bytes until the + next symbol. + + ``namebuf`` + Contains a buffer for the symbol name to be copied into, as a NUL + terminated string. + + ``buflen`` + Contains the length of the bufer that may be used. + + +Returns +------- + +:ref:`OPAL_SUCCESS` + Found a symbol. +:ref:`OPAL_RESOURCE` + Did not find a symbol. diff --git a/doc/opal-api/opal-lookup-symbol-182.rst b/doc/opal-api/opal-lookup-symbol-182.rst new file mode 100644 index 000000000..06ab4baff --- /dev/null +++ b/doc/opal-api/opal-lookup-symbol-182.rst @@ -0,0 +1,35 @@ +.. _OPAL_SYM_TO_ADDR: + +OPAL_SYM_TO_ADDR +================ + +.. code-block:: c + + #define OPAL_SYM_TO_ADDR 182 + + static int64_t opal_sym_to_addr(const char *name, __be64 *symaddr, __be64 *symsize); + +This OPAL call looks up a firmware symbol name for its address. + +Arguments +--------- + + ``name`` + Contains a pointer to NUL terminated symbol name to be looked up. + + ``symaddr`` + Returns the start address of the symbol for the object which + contains addr or immediately precedes addr. + + ``symsize`` + Returns the size of the object, or the number of bytes until the + next symbol. + + +Returns +------- + +:ref:`OPAL_SUCCESS` + Found a symbol. +:ref:`OPAL_RESOURCE` + Did not find a symbol. diff --git a/include/opal-api.h b/include/opal-api.h index e90cab1e9..ab8fc721f 100644 --- a/include/opal-api.h +++ b/include/opal-api.h @@ -227,7 +227,9 @@ #define OPAL_SECVAR_ENQUEUE_UPDATE 178 #define OPAL_PHB_SET_OPTION 179 #define OPAL_PHB_GET_OPTION 180 -#define OPAL_LAST 180 +#define OPAL_ADDR_TO_SYM 181 +#define OPAL_SYM_TO_ADDR 182 +#define OPAL_LAST 182 #define QUIESCE_HOLD 1 /* Spin all calls at entry */ #define QUIESCE_REJECT 2 /* Fail all calls with OPAL_BUSY */