blob: 3e987ea81c68737094a393329de0780ec520592d [file] [log] [blame]
// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
/* Copyright 2013-2019 IBM Corp. */
#ifndef __STACKFRAME_H
#define __STACKFRAME_H
#include <mem-map.h>
#define STACK_ENTRY_OPAL_API 0 /* OPAL call */
#define STACK_ENTRY_HMI 0x0e60 /* Hypervisor maintenance */
#define STACK_ENTRY_RESET 0x0100 /* System reset */
#define STACK_ENTRY_SOFTPATCH 0x1500 /* Soft patch (denorm emulation) */
#if HAVE_BIG_ENDIAN
#define STACK_TOC_OFFSET 40
#else
#define STACK_TOC_OFFSET 24
#endif
/* Safety/ABI gap at top of stack */
#define STACK_TOP_GAP 0x100
/* Remaining stack space (gap included) */
#define NORMAL_STACK_SIZE (STACK_SIZE/2)
/* Emergency (re-entry) stack size */
#define EMERGENCY_STACK_SIZE (STACK_SIZE/2)
/* Offset to get to normal CPU stacks */
#define CPU_STACKS_OFFSET (CPU_STACKS_BASE + \
NORMAL_STACK_SIZE - STACK_TOP_GAP)
/* Offset to get to emergency CPU stacks */
#define EMERGENCY_CPU_STACKS_OFFSET (CPU_STACKS_BASE + NORMAL_STACK_SIZE + \
EMERGENCY_STACK_SIZE - STACK_TOP_GAP)
/* Gap below the stack. If our stack checker sees the stack below that
* gap, it will flag a stack overflow
*/
#define STACK_SAFETY_GAP 512
/* Warning threshold, if stack goes below that on mcount, print a
* warning.
*/
#define STACK_WARNING_GAP 2048
#define STACK_CHECK_GUARD_BASE 0xdeadf00dbaad300
#define STACK_INT_MAGIC 0xb1ab1af00ba1234ULL
#ifndef __ASSEMBLY__
#include <stdint.h>
#include <opal-api.h>
/* This is the struct used to save GPRs etc.. on OPAL entry
* and from some exceptions. It is not always entirely populated
* depending on the entry type
*/
struct stack_frame {
/* Standard 112-byte stack frame header (the minimum size required,
* using an 8-doubleword param save area). The callee (in C) may use
* lrsave; we declare these here so we don't get our own save area
* overwritten */
uint64_t backchain;
uint64_t crsave;
uint64_t lrsave;
uint64_t compiler_dw;
uint64_t linker_dw;
uint64_t tocsave;
uint64_t paramsave[8];
/* Space for stack-local vars used by asm. At present we only use
* one doubleword. */
uint64_t locals[1];
/* Interrupt entry magic value */
uint64_t magic;
/* Entry type */
uint64_t type;
/* GPR save area
*
* We don't necessarily save everything in here
*/
uint64_t gpr[32];
/* Other SPR saved
*
* Only for some exceptions.
*/
uint32_t cr;
uint32_t xer;
uint32_t dsisr;
uint64_t ctr;
uint64_t lr;
uint64_t pc;
uint64_t msr;
uint64_t cfar;
uint64_t srr0;
uint64_t srr1;
uint64_t hsrr0;
uint64_t hsrr1;
uint64_t dar;
} __attribute__((aligned(16)));
/* Backtrace entry */
struct bt_entry {
unsigned long sp;
unsigned long pc;
unsigned long exception_type;
unsigned long exception_pc;
};
/* Backtrace metadata */
struct bt_metadata {
unsigned int ents;
unsigned long token;
unsigned long r1_caller;
unsigned long pir;
};
/* Boot stack top */
extern void *boot_stack_top;
/* Create a backtrace */
void backtrace_create(struct bt_entry *entries, unsigned int max_ents,
struct bt_metadata *metadata);
/* Convert a backtrace to ASCII */
extern void backtrace_print(struct bt_entry *entries,
struct bt_metadata *metadata, char *out_buf,
unsigned int *len, bool symbols);
/* For use by debug code, create and print backtrace, uses a static buffer */
extern void backtrace(void);
/* For use by exception debug code, supply an r1 */
extern void backtrace_r1(uint64_t r1);
#ifdef STACK_CHECK_ENABLED
extern void check_stacks(void);
#else
static inline void check_stacks(void) { }
#endif
#endif /* __ASSEMBLY__ */
#endif /* __STACKFRAME_H */