Merge branch 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: (470 commits) x86: Fix comments of register/stack access functions perf tools: Replace %m with %a in sscanf hw-breakpoints: Keep track of user disabled breakpoints tracing/syscalls: Make syscall events print callbacks static tracing: Add DEFINE_EVENT(), DEFINE_SINGLE_EVENT() support to docbook perf: Don't free perf_mmap_data until work has been done perf_event: Fix compile error perf tools: Fix _GNU_SOURCE macro related strndup() build error trace_syscalls: Remove unused syscall_name_to_nr() trace_syscalls: Simplify syscall profile trace_syscalls: Remove duplicate init_enter_##sname() trace_syscalls: Add syscall_nr field to struct syscall_metadata trace_syscalls: Remove enter_id exit_id trace_syscalls: Set event_enter_##sname->data to its metadata trace_syscalls: Remove unused event_syscall_enter and event_syscall_exit perf_event: Initialize data.period in perf_swevent_hrtimer() perf probe: Simplify event naming perf probe: Add --list option for listing current probe events perf probe: Add argv_split() from lib/argv_split.c perf probe: Move probe event utility functions to probe-event.c ...
This commit is contained in:
@@ -10,6 +10,7 @@ header-y += ptrace-abi.h
|
||||
header-y += sigcontext32.h
|
||||
header-y += ucontext.h
|
||||
header-y += processor-flags.h
|
||||
header-y += hw_breakpoint.h
|
||||
|
||||
unifdef-y += e820.h
|
||||
unifdef-y += ist.h
|
||||
|
@@ -17,6 +17,7 @@
|
||||
|
||||
#include <linux/user.h>
|
||||
#include <linux/elfcore.h>
|
||||
#include <asm/debugreg.h>
|
||||
|
||||
/*
|
||||
* fill in the user structure for an a.out core dump
|
||||
@@ -32,14 +33,7 @@ static inline void aout_dump_thread(struct pt_regs *regs, struct user *dump)
|
||||
>> PAGE_SHIFT;
|
||||
dump->u_dsize -= dump->u_tsize;
|
||||
dump->u_ssize = 0;
|
||||
dump->u_debugreg[0] = current->thread.debugreg0;
|
||||
dump->u_debugreg[1] = current->thread.debugreg1;
|
||||
dump->u_debugreg[2] = current->thread.debugreg2;
|
||||
dump->u_debugreg[3] = current->thread.debugreg3;
|
||||
dump->u_debugreg[4] = 0;
|
||||
dump->u_debugreg[5] = 0;
|
||||
dump->u_debugreg[6] = current->thread.debugreg6;
|
||||
dump->u_debugreg[7] = current->thread.debugreg7;
|
||||
aout_dump_debugregs(dump);
|
||||
|
||||
if (dump->start_stack < TASK_SIZE)
|
||||
dump->u_ssize = ((unsigned long)(TASK_SIZE - dump->start_stack))
|
||||
|
@@ -18,6 +18,7 @@
|
||||
#define DR_TRAP1 (0x2) /* db1 */
|
||||
#define DR_TRAP2 (0x4) /* db2 */
|
||||
#define DR_TRAP3 (0x8) /* db3 */
|
||||
#define DR_TRAP_BITS (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)
|
||||
|
||||
#define DR_STEP (0x4000) /* single-step */
|
||||
#define DR_SWITCH (0x8000) /* task switch */
|
||||
@@ -49,6 +50,8 @@
|
||||
|
||||
#define DR_LOCAL_ENABLE_SHIFT 0 /* Extra shift to the local enable bit */
|
||||
#define DR_GLOBAL_ENABLE_SHIFT 1 /* Extra shift to the global enable bit */
|
||||
#define DR_LOCAL_ENABLE (0x1) /* Local enable for reg 0 */
|
||||
#define DR_GLOBAL_ENABLE (0x2) /* Global enable for reg 0 */
|
||||
#define DR_ENABLE_SIZE 2 /* 2 enable bits per register */
|
||||
|
||||
#define DR_LOCAL_ENABLE_MASK (0x55) /* Set local bits for all 4 regs */
|
||||
@@ -67,4 +70,34 @@
|
||||
#define DR_LOCAL_SLOWDOWN (0x100) /* Local slow the pipeline */
|
||||
#define DR_GLOBAL_SLOWDOWN (0x200) /* Global slow the pipeline */
|
||||
|
||||
/*
|
||||
* HW breakpoint additions
|
||||
*/
|
||||
#ifdef __KERNEL__
|
||||
|
||||
DECLARE_PER_CPU(unsigned long, cpu_dr7);
|
||||
|
||||
static inline void hw_breakpoint_disable(void)
|
||||
{
|
||||
/* Zero the control register for HW Breakpoint */
|
||||
set_debugreg(0UL, 7);
|
||||
|
||||
/* Zero-out the individual HW breakpoint address registers */
|
||||
set_debugreg(0UL, 0);
|
||||
set_debugreg(0UL, 1);
|
||||
set_debugreg(0UL, 2);
|
||||
set_debugreg(0UL, 3);
|
||||
}
|
||||
|
||||
static inline int hw_breakpoint_active(void)
|
||||
{
|
||||
return __get_cpu_var(cpu_dr7) & DR_GLOBAL_ENABLE_MASK;
|
||||
}
|
||||
|
||||
extern void aout_dump_debugregs(struct user *dump);
|
||||
|
||||
extern void hw_breakpoint_restore(void);
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* _ASM_X86_DEBUGREG_H */
|
||||
|
@@ -20,11 +20,11 @@ typedef struct {
|
||||
unsigned int irq_call_count;
|
||||
unsigned int irq_tlb_count;
|
||||
#endif
|
||||
#ifdef CONFIG_X86_MCE
|
||||
#ifdef CONFIG_X86_THERMAL_VECTOR
|
||||
unsigned int irq_thermal_count;
|
||||
# ifdef CONFIG_X86_MCE_THRESHOLD
|
||||
#endif
|
||||
#ifdef CONFIG_X86_MCE_THRESHOLD
|
||||
unsigned int irq_threshold_count;
|
||||
# endif
|
||||
#endif
|
||||
} ____cacheline_aligned irq_cpustat_t;
|
||||
|
||||
|
73
arch/x86/include/asm/hw_breakpoint.h
Normal file
73
arch/x86/include/asm/hw_breakpoint.h
Normal file
@@ -0,0 +1,73 @@
|
||||
#ifndef _I386_HW_BREAKPOINT_H
|
||||
#define _I386_HW_BREAKPOINT_H
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#define __ARCH_HW_BREAKPOINT_H
|
||||
|
||||
/*
|
||||
* The name should probably be something dealt in
|
||||
* a higher level. While dealing with the user
|
||||
* (display/resolving)
|
||||
*/
|
||||
struct arch_hw_breakpoint {
|
||||
char *name; /* Contains name of the symbol to set bkpt */
|
||||
unsigned long address;
|
||||
u8 len;
|
||||
u8 type;
|
||||
};
|
||||
|
||||
#include <linux/kdebug.h>
|
||||
#include <linux/percpu.h>
|
||||
#include <linux/list.h>
|
||||
|
||||
/* Available HW breakpoint length encodings */
|
||||
#define X86_BREAKPOINT_LEN_1 0x40
|
||||
#define X86_BREAKPOINT_LEN_2 0x44
|
||||
#define X86_BREAKPOINT_LEN_4 0x4c
|
||||
#define X86_BREAKPOINT_LEN_EXECUTE 0x40
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
#define X86_BREAKPOINT_LEN_8 0x48
|
||||
#endif
|
||||
|
||||
/* Available HW breakpoint type encodings */
|
||||
|
||||
/* trigger on instruction execute */
|
||||
#define X86_BREAKPOINT_EXECUTE 0x80
|
||||
/* trigger on memory write */
|
||||
#define X86_BREAKPOINT_WRITE 0x81
|
||||
/* trigger on memory read or write */
|
||||
#define X86_BREAKPOINT_RW 0x83
|
||||
|
||||
/* Total number of available HW breakpoint registers */
|
||||
#define HBP_NUM 4
|
||||
|
||||
struct perf_event;
|
||||
struct pmu;
|
||||
|
||||
extern int arch_check_va_in_userspace(unsigned long va, u8 hbp_len);
|
||||
extern int arch_validate_hwbkpt_settings(struct perf_event *bp,
|
||||
struct task_struct *tsk);
|
||||
extern int hw_breakpoint_exceptions_notify(struct notifier_block *unused,
|
||||
unsigned long val, void *data);
|
||||
|
||||
|
||||
int arch_install_hw_breakpoint(struct perf_event *bp);
|
||||
void arch_uninstall_hw_breakpoint(struct perf_event *bp);
|
||||
void hw_breakpoint_pmu_read(struct perf_event *bp);
|
||||
void hw_breakpoint_pmu_unthrottle(struct perf_event *bp);
|
||||
|
||||
extern void
|
||||
arch_fill_perf_breakpoint(struct perf_event *bp);
|
||||
|
||||
unsigned long encode_dr7(int drnum, unsigned int len, unsigned int type);
|
||||
int decode_dr7(unsigned long dr7, int bpnum, unsigned *len, unsigned *type);
|
||||
|
||||
extern int arch_bp_generic_fields(int x86_len, int x86_type,
|
||||
int *gen_len, int *gen_type);
|
||||
|
||||
extern struct pmu perf_ops_bp;
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* _I386_HW_BREAKPOINT_H */
|
||||
|
220
arch/x86/include/asm/inat.h
Normal file
220
arch/x86/include/asm/inat.h
Normal file
@@ -0,0 +1,220 @@
|
||||
#ifndef _ASM_X86_INAT_H
|
||||
#define _ASM_X86_INAT_H
|
||||
/*
|
||||
* x86 instruction attributes
|
||||
*
|
||||
* Written by Masami Hiramatsu <mhiramat@redhat.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
#include <asm/inat_types.h>
|
||||
|
||||
/*
|
||||
* Internal bits. Don't use bitmasks directly, because these bits are
|
||||
* unstable. You should use checking functions.
|
||||
*/
|
||||
|
||||
#define INAT_OPCODE_TABLE_SIZE 256
|
||||
#define INAT_GROUP_TABLE_SIZE 8
|
||||
|
||||
/* Legacy last prefixes */
|
||||
#define INAT_PFX_OPNDSZ 1 /* 0x66 */ /* LPFX1 */
|
||||
#define INAT_PFX_REPE 2 /* 0xF3 */ /* LPFX2 */
|
||||
#define INAT_PFX_REPNE 3 /* 0xF2 */ /* LPFX3 */
|
||||
/* Other Legacy prefixes */
|
||||
#define INAT_PFX_LOCK 4 /* 0xF0 */
|
||||
#define INAT_PFX_CS 5 /* 0x2E */
|
||||
#define INAT_PFX_DS 6 /* 0x3E */
|
||||
#define INAT_PFX_ES 7 /* 0x26 */
|
||||
#define INAT_PFX_FS 8 /* 0x64 */
|
||||
#define INAT_PFX_GS 9 /* 0x65 */
|
||||
#define INAT_PFX_SS 10 /* 0x36 */
|
||||
#define INAT_PFX_ADDRSZ 11 /* 0x67 */
|
||||
/* x86-64 REX prefix */
|
||||
#define INAT_PFX_REX 12 /* 0x4X */
|
||||
/* AVX VEX prefixes */
|
||||
#define INAT_PFX_VEX2 13 /* 2-bytes VEX prefix */
|
||||
#define INAT_PFX_VEX3 14 /* 3-bytes VEX prefix */
|
||||
|
||||
#define INAT_LSTPFX_MAX 3
|
||||
#define INAT_LGCPFX_MAX 11
|
||||
|
||||
/* Immediate size */
|
||||
#define INAT_IMM_BYTE 1
|
||||
#define INAT_IMM_WORD 2
|
||||
#define INAT_IMM_DWORD 3
|
||||
#define INAT_IMM_QWORD 4
|
||||
#define INAT_IMM_PTR 5
|
||||
#define INAT_IMM_VWORD32 6
|
||||
#define INAT_IMM_VWORD 7
|
||||
|
||||
/* Legacy prefix */
|
||||
#define INAT_PFX_OFFS 0
|
||||
#define INAT_PFX_BITS 4
|
||||
#define INAT_PFX_MAX ((1 << INAT_PFX_BITS) - 1)
|
||||
#define INAT_PFX_MASK (INAT_PFX_MAX << INAT_PFX_OFFS)
|
||||
/* Escape opcodes */
|
||||
#define INAT_ESC_OFFS (INAT_PFX_OFFS + INAT_PFX_BITS)
|
||||
#define INAT_ESC_BITS 2
|
||||
#define INAT_ESC_MAX ((1 << INAT_ESC_BITS) - 1)
|
||||
#define INAT_ESC_MASK (INAT_ESC_MAX << INAT_ESC_OFFS)
|
||||
/* Group opcodes (1-16) */
|
||||
#define INAT_GRP_OFFS (INAT_ESC_OFFS + INAT_ESC_BITS)
|
||||
#define INAT_GRP_BITS 5
|
||||
#define INAT_GRP_MAX ((1 << INAT_GRP_BITS) - 1)
|
||||
#define INAT_GRP_MASK (INAT_GRP_MAX << INAT_GRP_OFFS)
|
||||
/* Immediates */
|
||||
#define INAT_IMM_OFFS (INAT_GRP_OFFS + INAT_GRP_BITS)
|
||||
#define INAT_IMM_BITS 3
|
||||
#define INAT_IMM_MASK (((1 << INAT_IMM_BITS) - 1) << INAT_IMM_OFFS)
|
||||
/* Flags */
|
||||
#define INAT_FLAG_OFFS (INAT_IMM_OFFS + INAT_IMM_BITS)
|
||||
#define INAT_MODRM (1 << (INAT_FLAG_OFFS))
|
||||
#define INAT_FORCE64 (1 << (INAT_FLAG_OFFS + 1))
|
||||
#define INAT_SCNDIMM (1 << (INAT_FLAG_OFFS + 2))
|
||||
#define INAT_MOFFSET (1 << (INAT_FLAG_OFFS + 3))
|
||||
#define INAT_VARIANT (1 << (INAT_FLAG_OFFS + 4))
|
||||
#define INAT_VEXOK (1 << (INAT_FLAG_OFFS + 5))
|
||||
#define INAT_VEXONLY (1 << (INAT_FLAG_OFFS + 6))
|
||||
/* Attribute making macros for attribute tables */
|
||||
#define INAT_MAKE_PREFIX(pfx) (pfx << INAT_PFX_OFFS)
|
||||
#define INAT_MAKE_ESCAPE(esc) (esc << INAT_ESC_OFFS)
|
||||
#define INAT_MAKE_GROUP(grp) ((grp << INAT_GRP_OFFS) | INAT_MODRM)
|
||||
#define INAT_MAKE_IMM(imm) (imm << INAT_IMM_OFFS)
|
||||
|
||||
/* Attribute search APIs */
|
||||
extern insn_attr_t inat_get_opcode_attribute(insn_byte_t opcode);
|
||||
extern insn_attr_t inat_get_escape_attribute(insn_byte_t opcode,
|
||||
insn_byte_t last_pfx,
|
||||
insn_attr_t esc_attr);
|
||||
extern insn_attr_t inat_get_group_attribute(insn_byte_t modrm,
|
||||
insn_byte_t last_pfx,
|
||||
insn_attr_t esc_attr);
|
||||
extern insn_attr_t inat_get_avx_attribute(insn_byte_t opcode,
|
||||
insn_byte_t vex_m,
|
||||
insn_byte_t vex_pp);
|
||||
|
||||
/* Attribute checking functions */
|
||||
static inline int inat_is_legacy_prefix(insn_attr_t attr)
|
||||
{
|
||||
attr &= INAT_PFX_MASK;
|
||||
return attr && attr <= INAT_LGCPFX_MAX;
|
||||
}
|
||||
|
||||
static inline int inat_is_address_size_prefix(insn_attr_t attr)
|
||||
{
|
||||
return (attr & INAT_PFX_MASK) == INAT_PFX_ADDRSZ;
|
||||
}
|
||||
|
||||
static inline int inat_is_operand_size_prefix(insn_attr_t attr)
|
||||
{
|
||||
return (attr & INAT_PFX_MASK) == INAT_PFX_OPNDSZ;
|
||||
}
|
||||
|
||||
static inline int inat_is_rex_prefix(insn_attr_t attr)
|
||||
{
|
||||
return (attr & INAT_PFX_MASK) == INAT_PFX_REX;
|
||||
}
|
||||
|
||||
static inline int inat_last_prefix_id(insn_attr_t attr)
|
||||
{
|
||||
if ((attr & INAT_PFX_MASK) > INAT_LSTPFX_MAX)
|
||||
return 0;
|
||||
else
|
||||
return attr & INAT_PFX_MASK;
|
||||
}
|
||||
|
||||
static inline int inat_is_vex_prefix(insn_attr_t attr)
|
||||
{
|
||||
attr &= INAT_PFX_MASK;
|
||||
return attr == INAT_PFX_VEX2 || attr == INAT_PFX_VEX3;
|
||||
}
|
||||
|
||||
static inline int inat_is_vex3_prefix(insn_attr_t attr)
|
||||
{
|
||||
return (attr & INAT_PFX_MASK) == INAT_PFX_VEX3;
|
||||
}
|
||||
|
||||
static inline int inat_is_escape(insn_attr_t attr)
|
||||
{
|
||||
return attr & INAT_ESC_MASK;
|
||||
}
|
||||
|
||||
static inline int inat_escape_id(insn_attr_t attr)
|
||||
{
|
||||
return (attr & INAT_ESC_MASK) >> INAT_ESC_OFFS;
|
||||
}
|
||||
|
||||
static inline int inat_is_group(insn_attr_t attr)
|
||||
{
|
||||
return attr & INAT_GRP_MASK;
|
||||
}
|
||||
|
||||
static inline int inat_group_id(insn_attr_t attr)
|
||||
{
|
||||
return (attr & INAT_GRP_MASK) >> INAT_GRP_OFFS;
|
||||
}
|
||||
|
||||
static inline int inat_group_common_attribute(insn_attr_t attr)
|
||||
{
|
||||
return attr & ~INAT_GRP_MASK;
|
||||
}
|
||||
|
||||
static inline int inat_has_immediate(insn_attr_t attr)
|
||||
{
|
||||
return attr & INAT_IMM_MASK;
|
||||
}
|
||||
|
||||
static inline int inat_immediate_size(insn_attr_t attr)
|
||||
{
|
||||
return (attr & INAT_IMM_MASK) >> INAT_IMM_OFFS;
|
||||
}
|
||||
|
||||
static inline int inat_has_modrm(insn_attr_t attr)
|
||||
{
|
||||
return attr & INAT_MODRM;
|
||||
}
|
||||
|
||||
static inline int inat_is_force64(insn_attr_t attr)
|
||||
{
|
||||
return attr & INAT_FORCE64;
|
||||
}
|
||||
|
||||
static inline int inat_has_second_immediate(insn_attr_t attr)
|
||||
{
|
||||
return attr & INAT_SCNDIMM;
|
||||
}
|
||||
|
||||
static inline int inat_has_moffset(insn_attr_t attr)
|
||||
{
|
||||
return attr & INAT_MOFFSET;
|
||||
}
|
||||
|
||||
static inline int inat_has_variant(insn_attr_t attr)
|
||||
{
|
||||
return attr & INAT_VARIANT;
|
||||
}
|
||||
|
||||
static inline int inat_accept_vex(insn_attr_t attr)
|
||||
{
|
||||
return attr & INAT_VEXOK;
|
||||
}
|
||||
|
||||
static inline int inat_must_vex(insn_attr_t attr)
|
||||
{
|
||||
return attr & INAT_VEXONLY;
|
||||
}
|
||||
#endif
|
29
arch/x86/include/asm/inat_types.h
Normal file
29
arch/x86/include/asm/inat_types.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#ifndef _ASM_X86_INAT_TYPES_H
|
||||
#define _ASM_X86_INAT_TYPES_H
|
||||
/*
|
||||
* x86 instruction attributes
|
||||
*
|
||||
* Written by Masami Hiramatsu <mhiramat@redhat.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
/* Instruction attributes */
|
||||
typedef unsigned int insn_attr_t;
|
||||
typedef unsigned char insn_byte_t;
|
||||
typedef signed int insn_value_t;
|
||||
|
||||
#endif
|
184
arch/x86/include/asm/insn.h
Normal file
184
arch/x86/include/asm/insn.h
Normal file
@@ -0,0 +1,184 @@
|
||||
#ifndef _ASM_X86_INSN_H
|
||||
#define _ASM_X86_INSN_H
|
||||
/*
|
||||
* x86 instruction analysis
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* Copyright (C) IBM Corporation, 2009
|
||||
*/
|
||||
|
||||
/* insn_attr_t is defined in inat.h */
|
||||
#include <asm/inat.h>
|
||||
|
||||
struct insn_field {
|
||||
union {
|
||||
insn_value_t value;
|
||||
insn_byte_t bytes[4];
|
||||
};
|
||||
/* !0 if we've run insn_get_xxx() for this field */
|
||||
unsigned char got;
|
||||
unsigned char nbytes;
|
||||
};
|
||||
|
||||
struct insn {
|
||||
struct insn_field prefixes; /*
|
||||
* Prefixes
|
||||
* prefixes.bytes[3]: last prefix
|
||||
*/
|
||||
struct insn_field rex_prefix; /* REX prefix */
|
||||
struct insn_field vex_prefix; /* VEX prefix */
|
||||
struct insn_field opcode; /*
|
||||
* opcode.bytes[0]: opcode1
|
||||
* opcode.bytes[1]: opcode2
|
||||
* opcode.bytes[2]: opcode3
|
||||
*/
|
||||
struct insn_field modrm;
|
||||
struct insn_field sib;
|
||||
struct insn_field displacement;
|
||||
union {
|
||||
struct insn_field immediate;
|
||||
struct insn_field moffset1; /* for 64bit MOV */
|
||||
struct insn_field immediate1; /* for 64bit imm or off16/32 */
|
||||
};
|
||||
union {
|
||||
struct insn_field moffset2; /* for 64bit MOV */
|
||||
struct insn_field immediate2; /* for 64bit imm or seg16 */
|
||||
};
|
||||
|
||||
insn_attr_t attr;
|
||||
unsigned char opnd_bytes;
|
||||
unsigned char addr_bytes;
|
||||
unsigned char length;
|
||||
unsigned char x86_64;
|
||||
|
||||
const insn_byte_t *kaddr; /* kernel address of insn to analyze */
|
||||
const insn_byte_t *next_byte;
|
||||
};
|
||||
|
||||
#define X86_MODRM_MOD(modrm) (((modrm) & 0xc0) >> 6)
|
||||
#define X86_MODRM_REG(modrm) (((modrm) & 0x38) >> 3)
|
||||
#define X86_MODRM_RM(modrm) ((modrm) & 0x07)
|
||||
|
||||
#define X86_SIB_SCALE(sib) (((sib) & 0xc0) >> 6)
|
||||
#define X86_SIB_INDEX(sib) (((sib) & 0x38) >> 3)
|
||||
#define X86_SIB_BASE(sib) ((sib) & 0x07)
|
||||
|
||||
#define X86_REX_W(rex) ((rex) & 8)
|
||||
#define X86_REX_R(rex) ((rex) & 4)
|
||||
#define X86_REX_X(rex) ((rex) & 2)
|
||||
#define X86_REX_B(rex) ((rex) & 1)
|
||||
|
||||
/* VEX bit flags */
|
||||
#define X86_VEX_W(vex) ((vex) & 0x80) /* VEX3 Byte2 */
|
||||
#define X86_VEX_R(vex) ((vex) & 0x80) /* VEX2/3 Byte1 */
|
||||
#define X86_VEX_X(vex) ((vex) & 0x40) /* VEX3 Byte1 */
|
||||
#define X86_VEX_B(vex) ((vex) & 0x20) /* VEX3 Byte1 */
|
||||
#define X86_VEX_L(vex) ((vex) & 0x04) /* VEX3 Byte2, VEX2 Byte1 */
|
||||
/* VEX bit fields */
|
||||
#define X86_VEX3_M(vex) ((vex) & 0x1f) /* VEX3 Byte1 */
|
||||
#define X86_VEX2_M 1 /* VEX2.M always 1 */
|
||||
#define X86_VEX_V(vex) (((vex) & 0x78) >> 3) /* VEX3 Byte2, VEX2 Byte1 */
|
||||
#define X86_VEX_P(vex) ((vex) & 0x03) /* VEX3 Byte2, VEX2 Byte1 */
|
||||
#define X86_VEX_M_MAX 0x1f /* VEX3.M Maximum value */
|
||||
|
||||
/* The last prefix is needed for two-byte and three-byte opcodes */
|
||||
static inline insn_byte_t insn_last_prefix(struct insn *insn)
|
||||
{
|
||||
return insn->prefixes.bytes[3];
|
||||
}
|
||||
|
||||
extern void insn_init(struct insn *insn, const void *kaddr, int x86_64);
|
||||
extern void insn_get_prefixes(struct insn *insn);
|
||||
extern void insn_get_opcode(struct insn *insn);
|
||||
extern void insn_get_modrm(struct insn *insn);
|
||||
extern void insn_get_sib(struct insn *insn);
|
||||
extern void insn_get_displacement(struct insn *insn);
|
||||
extern void insn_get_immediate(struct insn *insn);
|
||||
extern void insn_get_length(struct insn *insn);
|
||||
|
||||
/* Attribute will be determined after getting ModRM (for opcode groups) */
|
||||
static inline void insn_get_attribute(struct insn *insn)
|
||||
{
|
||||
insn_get_modrm(insn);
|
||||
}
|
||||
|
||||
/* Instruction uses RIP-relative addressing */
|
||||
extern int insn_rip_relative(struct insn *insn);
|
||||
|
||||
/* Init insn for kernel text */
|
||||
static inline void kernel_insn_init(struct insn *insn, const void *kaddr)
|
||||
{
|
||||
#ifdef CONFIG_X86_64
|
||||
insn_init(insn, kaddr, 1);
|
||||
#else /* CONFIG_X86_32 */
|
||||
insn_init(insn, kaddr, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline int insn_is_avx(struct insn *insn)
|
||||
{
|
||||
if (!insn->prefixes.got)
|
||||
insn_get_prefixes(insn);
|
||||
return (insn->vex_prefix.value != 0);
|
||||
}
|
||||
|
||||
static inline insn_byte_t insn_vex_m_bits(struct insn *insn)
|
||||
{
|
||||
if (insn->vex_prefix.nbytes == 2) /* 2 bytes VEX */
|
||||
return X86_VEX2_M;
|
||||
else
|
||||
return X86_VEX3_M(insn->vex_prefix.bytes[1]);
|
||||
}
|
||||
|
||||
static inline insn_byte_t insn_vex_p_bits(struct insn *insn)
|
||||
{
|
||||
if (insn->vex_prefix.nbytes == 2) /* 2 bytes VEX */
|
||||
return X86_VEX_P(insn->vex_prefix.bytes[1]);
|
||||
else
|
||||
return X86_VEX_P(insn->vex_prefix.bytes[2]);
|
||||
}
|
||||
|
||||
/* Offset of each field from kaddr */
|
||||
static inline int insn_offset_rex_prefix(struct insn *insn)
|
||||
{
|
||||
return insn->prefixes.nbytes;
|
||||
}
|
||||
static inline int insn_offset_vex_prefix(struct insn *insn)
|
||||
{
|
||||
return insn_offset_rex_prefix(insn) + insn->rex_prefix.nbytes;
|
||||
}
|
||||
static inline int insn_offset_opcode(struct insn *insn)
|
||||
{
|
||||
return insn_offset_vex_prefix(insn) + insn->vex_prefix.nbytes;
|
||||
}
|
||||
static inline int insn_offset_modrm(struct insn *insn)
|
||||
{
|
||||
return insn_offset_opcode(insn) + insn->opcode.nbytes;
|
||||
}
|
||||
static inline int insn_offset_sib(struct insn *insn)
|
||||
{
|
||||
return insn_offset_modrm(insn) + insn->modrm.nbytes;
|
||||
}
|
||||
static inline int insn_offset_displacement(struct insn *insn)
|
||||
{
|
||||
return insn_offset_sib(insn) + insn->sib.nbytes;
|
||||
}
|
||||
static inline int insn_offset_immediate(struct insn *insn)
|
||||
{
|
||||
return insn_offset_displacement(insn) + insn->displacement.nbytes;
|
||||
}
|
||||
|
||||
#endif /* _ASM_X86_INSN_H */
|
@@ -108,6 +108,8 @@ struct mce_log {
|
||||
#define K8_MCE_THRESHOLD_BANK_5 (MCE_THRESHOLD_BASE + 5 * 9)
|
||||
#define K8_MCE_THRESHOLD_DRAM_ECC (MCE_THRESHOLD_BANK_4 + 0)
|
||||
|
||||
extern struct atomic_notifier_head x86_mce_decoder_chain;
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#include <linux/percpu.h>
|
||||
@@ -118,9 +120,11 @@ extern int mce_disabled;
|
||||
extern int mce_p5_enabled;
|
||||
|
||||
#ifdef CONFIG_X86_MCE
|
||||
void mcheck_init(struct cpuinfo_x86 *c);
|
||||
int mcheck_init(void);
|
||||
void mcheck_cpu_init(struct cpuinfo_x86 *c);
|
||||
#else
|
||||
static inline void mcheck_init(struct cpuinfo_x86 *c) {}
|
||||
static inline int mcheck_init(void) { return 0; }
|
||||
static inline void mcheck_cpu_init(struct cpuinfo_x86 *c) {}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_X86_ANCIENT_MCE
|
||||
@@ -214,5 +218,11 @@ void intel_init_thermal(struct cpuinfo_x86 *c);
|
||||
|
||||
void mce_log_therm_throt_event(__u64 status);
|
||||
|
||||
#ifdef CONFIG_X86_THERMAL_VECTOR
|
||||
extern void mcheck_intel_therm_init(void);
|
||||
#else
|
||||
static inline void mcheck_intel_therm_init(void) { }
|
||||
#endif
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* _ASM_X86_MCE_H */
|
||||
|
@@ -28,9 +28,20 @@
|
||||
*/
|
||||
#define ARCH_PERFMON_EVENT_MASK 0xffff
|
||||
|
||||
/*
|
||||
* filter mask to validate fixed counter events.
|
||||
* the following filters disqualify for fixed counters:
|
||||
* - inv
|
||||
* - edge
|
||||
* - cnt-mask
|
||||
* The other filters are supported by fixed counters.
|
||||
* The any-thread option is supported starting with v3.
|
||||
*/
|
||||
#define ARCH_PERFMON_EVENT_FILTER_MASK 0xff840000
|
||||
|
||||
#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL 0x3c
|
||||
#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK (0x00 << 8)
|
||||
#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX 0
|
||||
#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX 0
|
||||
#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT \
|
||||
(1 << (ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX))
|
||||
|
||||
|
@@ -30,6 +30,7 @@ struct mm_struct;
|
||||
#include <linux/math64.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#define HBP_NUM 4
|
||||
/*
|
||||
* Default implementation of macro that returns current
|
||||
* instruction pointer ("program counter").
|
||||
@@ -422,6 +423,8 @@ extern unsigned int xstate_size;
|
||||
extern void free_thread_xstate(struct task_struct *);
|
||||
extern struct kmem_cache *task_xstate_cachep;
|
||||
|
||||
struct perf_event;
|
||||
|
||||
struct thread_struct {
|
||||
/* Cached TLS descriptors: */
|
||||
struct desc_struct tls_array[GDT_ENTRY_TLS_ENTRIES];
|
||||
@@ -443,13 +446,10 @@ struct thread_struct {
|
||||
unsigned long fs;
|
||||
#endif
|
||||
unsigned long gs;
|
||||
/* Hardware debugging registers: */
|
||||
unsigned long debugreg0;
|
||||
unsigned long debugreg1;
|
||||
unsigned long debugreg2;
|
||||
unsigned long debugreg3;
|
||||
unsigned long debugreg6;
|
||||
unsigned long debugreg7;
|
||||
/* Save middle states of ptrace breakpoints */
|
||||
struct perf_event *ptrace_bps[HBP_NUM];
|
||||
/* Debug status used for traps, single steps, etc... */
|
||||
unsigned long debugreg6;
|
||||
/* Fault info: */
|
||||
unsigned long cr2;
|
||||
unsigned long trap_no;
|
||||
|
@@ -7,6 +7,7 @@
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#include <asm/segment.h>
|
||||
#include <asm/page_types.h>
|
||||
#endif
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
@@ -216,6 +217,67 @@ static inline unsigned long user_stack_pointer(struct pt_regs *regs)
|
||||
return regs->sp;
|
||||
}
|
||||
|
||||
/* Query offset/name of register from its name/offset */
|
||||
extern int regs_query_register_offset(const char *name);
|
||||
extern const char *regs_query_register_name(unsigned int offset);
|
||||
#define MAX_REG_OFFSET (offsetof(struct pt_regs, ss))
|
||||
|
||||
/**
|
||||
* 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. The @offset is the
|
||||
* offset of the register in struct pt_regs address which specified by @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);
|
||||
}
|
||||
|
||||
/**
|
||||
* regs_within_kernel_stack() - check the address in the stack
|
||||
* @regs: pt_regs which contains kernel stack pointer.
|
||||
* @addr: address which is checked.
|
||||
*
|
||||
* regs_within_kernel_stack() checks @addr is within the kernel stack page(s).
|
||||
* If @addr is within the kernel stack, it returns true. If not, returns false.
|
||||
*/
|
||||
static inline int regs_within_kernel_stack(struct pt_regs *regs,
|
||||
unsigned long addr)
|
||||
{
|
||||
return ((addr & ~(THREAD_SIZE - 1)) ==
|
||||
(kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1)));
|
||||
}
|
||||
|
||||
/**
|
||||
* regs_get_kernel_stack_nth() - get Nth entry of the stack
|
||||
* @regs: pt_regs which contains kernel stack pointer.
|
||||
* @n: stack entry number.
|
||||
*
|
||||
* regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which
|
||||
* is specified by @regs. If the @n th entry is NOT in the kernel stack,
|
||||
* this returns 0.
|
||||
*/
|
||||
static inline unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs,
|
||||
unsigned int n)
|
||||
{
|
||||
unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs);
|
||||
addr += n;
|
||||
if (regs_within_kernel_stack(regs, (unsigned long)addr))
|
||||
return *addr;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get Nth argument at function call */
|
||||
extern unsigned long regs_get_argument_nth(struct pt_regs *regs,
|
||||
unsigned int n);
|
||||
|
||||
/*
|
||||
* These are defined as per linux/ptrace.h, which see.
|
||||
*/
|
||||
|
Reference in New Issue
Block a user