Discussion:
[Crash-utility] [PATCH 1/2] ppc64/opal: add a flag to determine if the kernel is running on OPAL firmware
Hari Bathini
2018-10-01 17:22:43 UTC
Permalink
Add PPC64 specific flag for kernels running on platforms based on
OPAL firmware. Use this flag before processing commands specific to
OPAL based systems.

Signed-off-by: Hari Bathini <***@linux.ibm.com>
---
defs.h | 8 ++++++++
ppc64.c | 36 ++++++++++++++++--------------------
2 files changed, 24 insertions(+), 20 deletions(-)

diff --git a/defs.h b/defs.h
index 5b64bb7..567992e 100644
--- a/defs.h
+++ b/defs.h
@@ -5963,6 +5963,12 @@ struct ppc64_elf_prstatus {

#ifdef PPC64

+struct ppc64_opal {
+ uint64_t base;
+ uint64_t entry;
+ uint64_t size;
+};
+
struct ppc64_vmemmap {
unsigned long phys;
unsigned long virt;
@@ -6013,6 +6019,7 @@ struct machine_specific {
ulong _page_accessed;
int (*is_kvaddr)(ulong);
int (*is_vmaddr)(ulong);
+ struct ppc64_opal opal;
};

void ppc64_init(int);
@@ -6030,6 +6037,7 @@ void ppc64_dump_machdep_table(ulong);
* in the kernel is also 0x40.
*/
#define RADIX_MMU (0x40)
+#define OPAL_FW (0x80)

#define REGION_SHIFT (60UL)
#define REGION_ID(addr) (((unsigned long)(addr)) >> REGION_SHIFT)
diff --git a/ppc64.c b/ppc64.c
index ee2f76f..cf41765 100644
--- a/ppc64.c
+++ b/ppc64.c
@@ -241,6 +241,7 @@ struct machine_specific book3e_machine_specific = {
.is_vmaddr = book3e_is_vmaddr,
};

+#define SKIBOOT_BASE 0x30000000

/*
* Do all necessary machine-specific setup here. This is called several
@@ -362,6 +363,16 @@ ppc64_init(int when)
struct machine_specific *m = machdep->machspec;

/*
+ * To determine if the kernel was running on OPAL based platform,
+ * use struct opal, which is populated with relevant values.
+ */
+ if (symbol_exists("opal")) {
+ get_symbol_data("opal", sizeof(struct ppc64_opal), &(m->opal));
+ if (m->opal.base == SKIBOOT_BASE)
+ machdep->flags |= OPAL_FW;
+ }
+
+ /*
* On Power ISA 3.0 based server processors, a kernel can
* run with radix MMU or standard MMU. Set the flag,
* if it is radix MMU.
@@ -712,6 +723,8 @@ ppc64_dump_machdep_table(ulong arg)
fprintf(fp, "%sSWAP_ENTRY_L4", others++ ? "|" : "");
if (machdep->flags & RADIX_MMU)
fprintf(fp, "%sRADIX_MMU", others++ ? "|" : "");
+ if (machdep->flags & OPAL_FW)
+ fprintf(fp, "%sOPAL_FW", others++ ? "|" : "");
fprintf(fp, ")\n");

fprintf(fp, " kvbase: %lx\n", machdep->kvbase);
@@ -2828,7 +2841,6 @@ ppc64_get_smp_cpus(void)
*/
#define SKIBOOT_CONSOLE_DUMP_START 0x31000000
#define SKIBOOT_CONSOLE_DUMP_SIZE 0x100000
-#define SKIBOOT_BASE 0x30000000
#define ASCII_UNLIMITED ((ulong)(-1) >> 1)

void
@@ -2841,10 +2853,6 @@ opalmsg(void)
uint64_t u64;
uint64_t limit64;
};
- struct opal {
- unsigned long long base;
- unsigned long long entry;
- } opal;
int i, a;
size_t typesz;
void *location;
@@ -2856,25 +2864,13 @@ opalmsg(void)
long count = SKIBOOT_CONSOLE_DUMP_SIZE;
ulonglong addr = SKIBOOT_CONSOLE_DUMP_START;

+ if (!(machdep->flags & OPAL_FW))
+ error(FATAL, "dump was not captured on OPAL based system");
+
if (CRASHDEBUG(4))
fprintf(fp, "<addr: %llx count: %ld (%s)>\n",
addr, count, "PHYSADDR");

- /*
- * OPAL based platform check
- * struct opal of BSS section and hence default value will be ZERO(0)
- * opal_init() in the kernel initializes this structure based on
- * the platform. Use it as a key to determine whether the dump
- * was taken on an OPAL based system or not.
- */
- if (symbol_exists("opal")) {
- get_symbol_data("opal", sizeof(struct opal), &opal);
- if (opal.base != SKIBOOT_BASE)
- error(FATAL, "dump was captured on non-PowerNV machine");
- } else {
- error(FATAL, "dump was captured on non-PowerNV machine");
- }
-
BZERO(&mem, sizeof(struct memloc));
lost = typesz = per_line = 0;
location = NULL;
Hari Bathini
2018-10-01 17:22:50 UTC
Permalink
On OPAL based systems, when a thread is running an OPAL API, the stack
pointer and instruction pointer would be pointing at OPAL address but
'bt' output for such thread would complain that the stack pointer is
invalid. Update error/log message for better context.

Signed-off-by: Hari Bathini <***@linux.ibm.com>
---
ppc64.c | 36 ++++++++++++++++++++++++++++++++----
1 file changed, 32 insertions(+), 4 deletions(-)

diff --git a/ppc64.c b/ppc64.c
index cf41765..041480b 100644
--- a/ppc64.c
+++ b/ppc64.c
@@ -65,8 +65,26 @@ static ulong hugepage_dir(ulong pte);
static ulong pgd_page_vaddr_l4(ulong pgd);
static ulong pud_page_vaddr_l4(ulong pud);
static ulong pmd_page_vaddr_l4(ulong pmd);
+static int is_opal_context(ulong sp, ulong nip);
void opalmsg(void);

+static int is_opal_context(ulong sp, ulong nip)
+{
+ uint64_t opal_start, opal_end;
+
+ if (!(machdep->flags & OPAL_FW))
+ return FALSE;
+
+ opal_start = machdep->machspec->opal.base;
+ opal_end = opal_start + machdep->machspec->opal.size;
+
+ if (((sp >= opal_start) && (sp < opal_end)) ||
+ ((nip >= opal_start) && (nip < opal_end)))
+ return TRUE;
+
+ return FALSE;
+}
+
static inline int is_hugepage(ulong pte)
{
if ((machdep->flags & BOOK3E) ||
@@ -2270,7 +2288,11 @@ ppc64_vmcore_stack_frame(struct bt_info *bt_in, ulong *nip, ulong *ksp)
{
struct ppc64_pt_regs *pt_regs;
unsigned long unip;
- int in_user_space = FALSE;
+ /*
+ * TRUE: task is running in a different context (userspace, OPAL..)
+ * FALSE: task is probably running in kernel space.
+ */
+ int out_of_context = FALSE;

pt_regs = (struct ppc64_pt_regs *)bt_in->machdep;
if (!pt_regs || !pt_regs->gpr[1]) {
@@ -2283,20 +2305,25 @@ ppc64_vmcore_stack_frame(struct bt_info *bt_in, ulong *nip, ulong *ksp)
bt_in->task);
return FALSE;
}
+
*ksp = pt_regs->gpr[1];
if (IS_KVADDR(*ksp)) {
readmem(*ksp+16, KVADDR, &unip, sizeof(ulong), "Regs NIP value",
FAULT_ON_ERROR);
*nip = unip;
} else {
+ *nip = pt_regs->nip;
if (IN_TASK_VMA(bt_in->task, *ksp)) {
fprintf(fp, "%0lx: Task is running in user space\n",
bt_in->task);
- in_user_space = TRUE;
+ out_of_context = TRUE;
+ } else if (is_opal_context(*ksp, *nip)) {
+ fprintf(fp, "%0lx: Task is running in OPAL (firmware) context\n",
+ bt_in->task);
+ out_of_context = TRUE;
} else
fprintf(fp, "%0lx: Invalid Stack Pointer %0lx\n",
bt_in->task, *ksp);
- *nip = pt_regs->nip;
}

if (bt_in->flags &&
@@ -2307,7 +2334,8 @@ ppc64_vmcore_stack_frame(struct bt_info *bt_in, ulong *nip, ulong *ksp)
* Print the collected regs for the active task
*/
ppc64_print_regs(pt_regs);
- if (in_user_space)
+
+ if (out_of_context)
return TRUE;
if (!IS_KVADDR(*ksp))
return FALSE;

Loading...