All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] Add OPAL_GET_SYMBOL / OPAL_LOOKUP_SYMBOL
@ 2020-02-28  3:07 Nicholas Piggin
  2020-03-06  2:42 ` Oliver O'Halloran
  0 siblings, 1 reply; 3+ messages in thread
From: Nicholas Piggin @ 2020-02-28  3:07 UTC (permalink / raw)
  To: skiboot; +Cc: linuxppc-dev, Nicholas Piggin

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 <npiggin@gmail.com>
---
 core/opal.c                             |  2 +
 core/utils.c                            | 92 +++++++++++++++++++++++--
 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, 168 insertions(+), 7 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 d6ff6027b..d9fc4fe05 100644
--- a/core/opal.c
+++ b/core/opal.c
@@ -142,6 +142,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_GET_SYMBOL:
+		case OPAL_LOOKUP_SYMBOL:
 			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 8fd63fcb7..5f0d5130b 100644
--- a/core/utils.c
+++ b/core/utils.c
@@ -48,40 +48,120 @@ 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 get_symbol(unsigned long addr, char **sym, char **sym_end, unsigned long *size)
 {
 	unsigned long prev = 0, next;
 	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;;
+			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 lookup_symbol(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;
+
+			if (get_symbol(addr, &sym, &sym_end, size) == 0) {
+				assert(!strcmp(name, "_end"));
+				*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_get_symbol(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 = get_symbol(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_GET_SYMBOL, opal_get_symbol, 5);
+
+static int64_t opal_lookup_symbol(const char *name, __be64 *symaddr, __be64 *symsize)
+{
+	unsigned long saddr;
+	unsigned long ssize;
+
+	saddr = lookup_symbol(name, &ssize);
+	if (!saddr)
+		return OPAL_RESOURCE;
+
+	*symaddr = cpu_to_be64(saddr);
+	*symsize = cpu_to_be64(ssize);
+
+	return OPAL_SUCCESS;
+}
+opal_call(OPAL_LOOKUP_SYMBOL, opal_lookup_symbol, 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 = get_symbol(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..a57de6c1c
--- /dev/null
+++ b/doc/opal-api/opal-get-symbol-181.rst
@@ -0,0 +1,42 @@
+.. _OPAL_GET_SYMBOL:
+
+OPAL_GET_SYMBOL
+================
+
+.. code-block:: c
+
+   #define OPAL_GET_SYMBOL			181
+
+   static int64_t opal_get_symbol(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..e9f6eba33
--- /dev/null
+++ b/doc/opal-api/opal-lookup-symbol-182.rst
@@ -0,0 +1,35 @@
+.. _OPAL_LOOKUP_SYMBOL:
+
+OPAL_LOOKUP_SYMBOL
+================
+
+.. code-block:: c
+
+   #define OPAL_LOOKUP_SYMBOL			182
+
+   static int64_t opal_lookup_symbol(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 5b07dea13..4474631a6 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_GET_SYMBOL				181
+#define OPAL_LOOKUP_SYMBOL			182
+#define OPAL_LAST				182
 
 #define QUIESCE_HOLD			1 /* Spin all calls at entry */
 #define QUIESCE_REJECT			2 /* Fail all calls with OPAL_BUSY */
-- 
2.23.0


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] Add OPAL_GET_SYMBOL / OPAL_LOOKUP_SYMBOL
  2020-02-28  3:07 [PATCH] Add OPAL_GET_SYMBOL / OPAL_LOOKUP_SYMBOL Nicholas Piggin
@ 2020-03-06  2:42 ` Oliver O'Halloran
  2020-03-07  0:15   ` Nicholas Piggin
  0 siblings, 1 reply; 3+ messages in thread
From: Oliver O'Halloran @ 2020-03-06  2:42 UTC (permalink / raw)
  To: Nicholas Piggin; +Cc: skiboot list, linuxppc-dev

On Fri, Feb 28, 2020 at 2:09 PM Nicholas Piggin <npiggin@gmail.com> wrote:
>
> 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 <npiggin@gmail.com>
> ---
>  core/opal.c                             |  2 +
>  core/utils.c                            | 92 +++++++++++++++++++++++--
>  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, 168 insertions(+), 7 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 d6ff6027b..d9fc4fe05 100644
> --- a/core/opal.c
> +++ b/core/opal.c
> @@ -142,6 +142,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_GET_SYMBOL:
> +               case OPAL_LOOKUP_SYMBOL:

These names are still awful :|

>                         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 8fd63fcb7..5f0d5130b 100644
> --- a/core/utils.c
> +++ b/core/utils.c
> @@ -48,40 +48,120 @@ 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 get_symbol(unsigned long addr, char **sym, char **sym_end, unsigned long *size)
>  {
>         unsigned long prev = 0, next;
>         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;;
> +                       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 lookup_symbol(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;
> +
> +                       if (get_symbol(addr, &sym, &sym_end, size) == 0) {
> +                               assert(!strcmp(name, "_end"));
> +                               *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_get_symbol(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 = get_symbol(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_GET_SYMBOL, opal_get_symbol, 5);
> +
> +static int64_t opal_lookup_symbol(const char *name, __be64 *symaddr, __be64 *symsize)
> +{
> +       unsigned long saddr;
> +       unsigned long ssize;
> +
> +       saddr = lookup_symbol(name, &ssize);
> +       if (!saddr)
> +               return OPAL_RESOURCE;
> +
> +       *symaddr = cpu_to_be64(saddr);
> +       *symsize = cpu_to_be64(ssize);
> +
> +       return OPAL_SUCCESS;
> +}
> +opal_call(OPAL_LOOKUP_SYMBOL, opal_lookup_symbol, 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 = get_symbol(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..a57de6c1c
> --- /dev/null
> +++ b/doc/opal-api/opal-get-symbol-181.rst
> @@ -0,0 +1,42 @@
> +.. _OPAL_GET_SYMBOL:
> +
> +OPAL_GET_SYMBOL
> +================
> +
> +.. code-block:: c
> +
> +   #define OPAL_GET_SYMBOL                     181
> +
> +   static int64_t opal_get_symbol(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..e9f6eba33
> --- /dev/null
> +++ b/doc/opal-api/opal-lookup-symbol-182.rst
> @@ -0,0 +1,35 @@
> +.. _OPAL_LOOKUP_SYMBOL:
> +
> +OPAL_LOOKUP_SYMBOL
> +================
> +
> +.. code-block:: c
> +
> +   #define OPAL_LOOKUP_SYMBOL                  182
> +
> +   static int64_t opal_lookup_symbol(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 5b07dea13..4474631a6 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_GET_SYMBOL                                181
> +#define OPAL_LOOKUP_SYMBOL                     182
> +#define OPAL_LAST                              182
>
>  #define QUIESCE_HOLD                   1 /* Spin all calls at entry */
>  #define QUIESCE_REJECT                 2 /* Fail all calls with OPAL_BUSY */
> --
> 2.23.0
>

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] Add OPAL_GET_SYMBOL / OPAL_LOOKUP_SYMBOL
  2020-03-06  2:42 ` Oliver O'Halloran
@ 2020-03-07  0:15   ` Nicholas Piggin
  0 siblings, 0 replies; 3+ messages in thread
From: Nicholas Piggin @ 2020-03-07  0:15 UTC (permalink / raw)
  To: Oliver O'Halloran; +Cc: skiboot list, linuxppc-dev

Oliver O'Halloran's on March 6, 2020 12:42 pm:
> On Fri, Feb 28, 2020 at 2:09 PM Nicholas Piggin <npiggin@gmail.com> wrote:
>>
>> 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 <npiggin@gmail.com>
>> ---
>>  core/opal.c                             |  2 +
>>  core/utils.c                            | 92 +++++++++++++++++++++++--
>>  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, 168 insertions(+), 7 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 d6ff6027b..d9fc4fe05 100644
>> --- a/core/opal.c
>> +++ b/core/opal.c
>> @@ -142,6 +142,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_GET_SYMBOL:
>> +               case OPAL_LOOKUP_SYMBOL:
> 
> These names are still awful :|

Ah yeah sorry I said I'd change them didn't I? Anyway don't merge before
the kernel is on board with the idea.

Thanks,
Nick

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2020-03-07  0:18 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-02-28  3:07 [PATCH] Add OPAL_GET_SYMBOL / OPAL_LOOKUP_SYMBOL Nicholas Piggin
2020-03-06  2:42 ` Oliver O'Halloran
2020-03-07  0:15   ` Nicholas Piggin

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.