/* Copyright 2013-2014 IBM Corp. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __STACKFRAME_H #define __STACKFRAME_H #include #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) */ /* 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 #ifndef __ASSEMBLY__ #include #include /* 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]; /* 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 cfar; uint64_t srr0; uint64_t srr1; uint64_t hsrr0; uint64_t hsrr1; uint64_t dar; } __attribute__((aligned(16))); /* Backtrace */ struct bt_entry { unsigned long sp; unsigned long pc; }; /* Boot stack top */ extern void *boot_stack_top; /* Create a backtrace */ void ___backtrace(struct bt_entry *entries, unsigned int *count, unsigned long r1, unsigned long *token, unsigned long *r1_caller); static inline void __backtrace(struct bt_entry *entries, unsigned int *count) { unsigned long token, r1_caller; ___backtrace(entries, count, (unsigned long)__builtin_frame_address(0), &token, &r1_caller); } /* Convert a backtrace to ASCII */ extern void ___print_backtrace(unsigned int pir, struct bt_entry *entries, unsigned int count, unsigned long token, unsigned long r1_caller, char *out_buf, unsigned int *len, bool symbols); static inline void __print_backtrace(unsigned int pir, struct bt_entry *entries, unsigned int count, char *out_buf, unsigned int *len, bool symbols) { ___print_backtrace(pir, entries, count, OPAL_LAST + 1, 0, out_buf, len, symbols); } /* For use by debug code, create and print backtrace, uses a static buffer */ extern void backtrace(void); #ifdef STACK_CHECK_ENABLED extern void check_stacks(void); #else static inline void check_stacks(void) { } #endif #endif /* __ASSEMBLY__ */ #endif /* __STACKFRAME_H */