diff options
Diffstat (limited to 'arch/arm/include')
-rw-r--r-- | arch/arm/include/asm/hwcap.h | 1 | ||||
-rw-r--r-- | arch/arm/include/asm/irq.h | 2 | ||||
-rw-r--r-- | arch/arm/include/asm/kexec.h | 22 | ||||
-rw-r--r-- | arch/arm/include/asm/mach/arch.h | 1 | ||||
-rw-r--r-- | arch/arm/include/asm/mach/irq.h | 1 | ||||
-rw-r--r-- | arch/arm/include/asm/ptrace.h | 36 | ||||
-rw-r--r-- | arch/arm/include/asm/tls.h | 46 | ||||
-rw-r--r-- | arch/arm/include/asm/vfpmacros.h | 18 |
8 files changed, 124 insertions, 3 deletions
diff --git a/arch/arm/include/asm/hwcap.h b/arch/arm/include/asm/hwcap.h index f7bd52b1c365..c1062c317103 100644 --- a/arch/arm/include/asm/hwcap.h +++ b/arch/arm/include/asm/hwcap.h @@ -19,6 +19,7 @@ #define HWCAP_NEON 4096 #define HWCAP_VFPv3 8192 #define HWCAP_VFPv3D16 16384 +#define HWCAP_TLS 32768 #if defined(__KERNEL__) && !defined(__ASSEMBLY__) /* diff --git a/arch/arm/include/asm/irq.h b/arch/arm/include/asm/irq.h index 237282f7c762..2721a5814cb9 100644 --- a/arch/arm/include/asm/irq.h +++ b/arch/arm/include/asm/irq.h @@ -7,6 +7,8 @@ #define irq_canonicalize(i) (i) #endif +#define NR_IRQS_LEGACY 16 + /* * Use this value to indicate lack of interrupt * capability diff --git a/arch/arm/include/asm/kexec.h b/arch/arm/include/asm/kexec.h index df15a0dc228e..8ec9ef5c3c7b 100644 --- a/arch/arm/include/asm/kexec.h +++ b/arch/arm/include/asm/kexec.h @@ -19,10 +19,26 @@ #ifndef __ASSEMBLY__ -struct kimage; -/* Provide a dummy definition to avoid build failures. */ +/** + * crash_setup_regs() - save registers for the panic kernel + * @newregs: registers are saved here + * @oldregs: registers to be saved (may be %NULL) + * + * Function copies machine registers from @oldregs to @newregs. If @oldregs is + * %NULL then current registers are stored there. + */ static inline void crash_setup_regs(struct pt_regs *newregs, - struct pt_regs *oldregs) { } + struct pt_regs *oldregs) +{ + if (oldregs) { + memcpy(newregs, oldregs, sizeof(*newregs)); + } else { + __asm__ __volatile__ ("stmia %0, {r0 - r15}" + : : "r" (&newregs->ARM_r0)); + __asm__ __volatile__ ("mrs %0, cpsr" + : "=r" (newregs->ARM_cpsr)); + } +} #endif /* __ASSEMBLY__ */ diff --git a/arch/arm/include/asm/mach/arch.h b/arch/arm/include/asm/mach/arch.h index d425f2b6efeb..8a0dd18ba642 100644 --- a/arch/arm/include/asm/mach/arch.h +++ b/arch/arm/include/asm/mach/arch.h @@ -20,6 +20,7 @@ struct machine_desc { * by assembler code in head.S, head-common.S */ unsigned int nr; /* architecture number */ + unsigned int nr_irqs; /* number of IRQs */ unsigned int phys_io; /* start of physical io */ unsigned int io_pg_offst; /* byte offset for io * page tabe entry */ diff --git a/arch/arm/include/asm/mach/irq.h b/arch/arm/include/asm/mach/irq.h index 8920b2d6e3b8..ce3eee9fe26c 100644 --- a/arch/arm/include/asm/mach/irq.h +++ b/arch/arm/include/asm/mach/irq.h @@ -17,6 +17,7 @@ struct seq_file; /* * This is internal. Do not use it. */ +extern unsigned int arch_nr_irqs; extern void (*init_arch_irq)(void); extern void init_FIQ(void); extern int show_fiq_list(struct seq_file *, void *); diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h index 9dcb11e59026..c974be8913a7 100644 --- a/arch/arm/include/asm/ptrace.h +++ b/arch/arm/include/asm/ptrace.h @@ -184,6 +184,42 @@ extern unsigned long profile_pc(struct pt_regs *regs); #define predicate(x) ((x) & 0xf0000000) #define PREDICATE_ALWAYS 0xe0000000 +/* + * kprobe-based event tracer support + */ +#include <linux/stddef.h> +#include <linux/types.h> +#define MAX_REG_OFFSET (offsetof(struct pt_regs, ARM_ORIG_r0)) + +extern int regs_query_register_offset(const char *name); +extern const char *regs_query_register_name(unsigned int offset); +extern bool regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr); +extern unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, + unsigned int n); + +/** + * regs_get_register() - get register value from its offset + * @regs: pt_regs from which register value is gotten + * @offset: offset number of the register. + * + * regs_get_register returns the value of a register whose offset from @regs. + * The @offset is the offset of the register in struct pt_regs. + * If @offset is bigger than MAX_REG_OFFSET, this returns 0. + */ +static inline unsigned long regs_get_register(struct pt_regs *regs, + unsigned int offset) +{ + if (unlikely(offset > MAX_REG_OFFSET)) + return 0; + return *(unsigned long *)((unsigned long)regs + offset); +} + +/* Valid only for Kernel mode traps. */ +static inline unsigned long kernel_stack_pointer(struct pt_regs *regs) +{ + return regs->ARM_sp; +} + #endif /* __KERNEL__ */ #endif /* __ASSEMBLY__ */ diff --git a/arch/arm/include/asm/tls.h b/arch/arm/include/asm/tls.h new file mode 100644 index 000000000000..e71d6ff8d104 --- /dev/null +++ b/arch/arm/include/asm/tls.h @@ -0,0 +1,46 @@ +#ifndef __ASMARM_TLS_H +#define __ASMARM_TLS_H + +#ifdef __ASSEMBLY__ + .macro set_tls_none, tp, tmp1, tmp2 + .endm + + .macro set_tls_v6k, tp, tmp1, tmp2 + mcr p15, 0, \tp, c13, c0, 3 @ set TLS register + .endm + + .macro set_tls_v6, tp, tmp1, tmp2 + ldr \tmp1, =elf_hwcap + ldr \tmp1, [\tmp1, #0] + mov \tmp2, #0xffff0fff + tst \tmp1, #HWCAP_TLS @ hardware TLS available? + mcrne p15, 0, \tp, c13, c0, 3 @ yes, set TLS register + streq \tp, [\tmp2, #-15] @ set TLS value at 0xffff0ff0 + .endm + + .macro set_tls_software, tp, tmp1, tmp2 + mov \tmp1, #0xffff0fff + str \tp, [\tmp1, #-15] @ set TLS value at 0xffff0ff0 + .endm +#endif + +#ifdef CONFIG_TLS_REG_EMUL +#define tls_emu 1 +#define has_tls_reg 1 +#define set_tls set_tls_none +#elif __LINUX_ARM_ARCH__ >= 7 || \ + (__LINUX_ARM_ARCH__ == 6 && defined(CONFIG_CPU_32v6K)) +#define tls_emu 0 +#define has_tls_reg 1 +#define set_tls set_tls_v6k +#elif __LINUX_ARM_ARCH__ == 6 +#define tls_emu 0 +#define has_tls_reg (elf_hwcap & HWCAP_TLS) +#define set_tls set_tls_v6 +#else +#define tls_emu 0 +#define has_tls_reg 0 +#define set_tls set_tls_software +#endif + +#endif /* __ASMARM_TLS_H */ diff --git a/arch/arm/include/asm/vfpmacros.h b/arch/arm/include/asm/vfpmacros.h index 422f3cc204a2..3d5fc41ae8d3 100644 --- a/arch/arm/include/asm/vfpmacros.h +++ b/arch/arm/include/asm/vfpmacros.h @@ -3,6 +3,8 @@ * * Assembler-only file containing VFP macros and register definitions. */ +#include <asm/hwcap.h> + #include "vfp.h" @ Macros to allow building with old toolkits (with no VFP support) @@ -22,12 +24,20 @@ LDC p11, cr0, [\base],#32*4 @ FLDMIAD \base!, {d0-d15} #endif #ifdef CONFIG_VFPv3 +#if __LINUX_ARM_ARCH__ <= 6 + ldr \tmp, =elf_hwcap @ may not have MVFR regs + ldr \tmp, [\tmp, #0] + tst \tmp, #HWCAP_VFPv3D16 + ldceq p11, cr0, [\base],#32*4 @ FLDMIAD \base!, {d16-d31} + addne \base, \base, #32*4 @ step over unused register space +#else VFPFMRX \tmp, MVFR0 @ Media and VFP Feature Register 0 and \tmp, \tmp, #MVFR0_A_SIMD_MASK @ A_SIMD field cmp \tmp, #2 @ 32 x 64bit registers? ldceql p11, cr0, [\base],#32*4 @ FLDMIAD \base!, {d16-d31} addne \base, \base, #32*4 @ step over unused register space #endif +#endif .endm @ write all the working registers out of the VFP @@ -38,10 +48,18 @@ STC p11, cr0, [\base],#32*4 @ FSTMIAD \base!, {d0-d15} #endif #ifdef CONFIG_VFPv3 +#if __LINUX_ARM_ARCH__ <= 6 + ldr \tmp, =elf_hwcap @ may not have MVFR regs + ldr \tmp, [\tmp, #0] + tst \tmp, #HWCAP_VFPv3D16 + stceq p11, cr0, [\base],#32*4 @ FSTMIAD \base!, {d16-d31} + addne \base, \base, #32*4 @ step over unused register space +#else VFPFMRX \tmp, MVFR0 @ Media and VFP Feature Register 0 and \tmp, \tmp, #MVFR0_A_SIMD_MASK @ A_SIMD field cmp \tmp, #2 @ 32 x 64bit registers? stceql p11, cr0, [\base],#32*4 @ FSTMIAD \base!, {d16-d31} addne \base, \base, #32*4 @ step over unused register space #endif +#endif .endm |