1c5e63197SJiri Olsa #include <linux/errno.h> 2c5e63197SJiri Olsa #include <linux/kernel.h> 34018994fSJiri Olsa #include <linux/sched.h> 468db0cf1SIngo Molnar #include <linux/sched/task_stack.h> 54018994fSJiri Olsa #include <linux/perf_event.h> 6c5e63197SJiri Olsa #include <linux/bug.h> 7c5e63197SJiri Olsa #include <linux/stddef.h> 8c5e63197SJiri Olsa #include <asm/perf_regs.h> 9c5e63197SJiri Olsa #include <asm/ptrace.h> 10c5e63197SJiri Olsa 11c5e63197SJiri Olsa #ifdef CONFIG_X86_32 12c5e63197SJiri Olsa #define PERF_REG_X86_MAX PERF_REG_X86_32_MAX 13c5e63197SJiri Olsa #else 14c5e63197SJiri Olsa #define PERF_REG_X86_MAX PERF_REG_X86_64_MAX 15c5e63197SJiri Olsa #endif 16c5e63197SJiri Olsa 17c5e63197SJiri Olsa #define PT_REGS_OFFSET(id, r) [id] = offsetof(struct pt_regs, r) 18c5e63197SJiri Olsa 19c5e63197SJiri Olsa static unsigned int pt_regs_offset[PERF_REG_X86_MAX] = { 20c5e63197SJiri Olsa PT_REGS_OFFSET(PERF_REG_X86_AX, ax), 21c5e63197SJiri Olsa PT_REGS_OFFSET(PERF_REG_X86_BX, bx), 22c5e63197SJiri Olsa PT_REGS_OFFSET(PERF_REG_X86_CX, cx), 23c5e63197SJiri Olsa PT_REGS_OFFSET(PERF_REG_X86_DX, dx), 24c5e63197SJiri Olsa PT_REGS_OFFSET(PERF_REG_X86_SI, si), 25c5e63197SJiri Olsa PT_REGS_OFFSET(PERF_REG_X86_DI, di), 26c5e63197SJiri Olsa PT_REGS_OFFSET(PERF_REG_X86_BP, bp), 27c5e63197SJiri Olsa PT_REGS_OFFSET(PERF_REG_X86_SP, sp), 28c5e63197SJiri Olsa PT_REGS_OFFSET(PERF_REG_X86_IP, ip), 29c5e63197SJiri Olsa PT_REGS_OFFSET(PERF_REG_X86_FLAGS, flags), 30c5e63197SJiri Olsa PT_REGS_OFFSET(PERF_REG_X86_CS, cs), 31c5e63197SJiri Olsa PT_REGS_OFFSET(PERF_REG_X86_SS, ss), 32c5e63197SJiri Olsa #ifdef CONFIG_X86_32 33c5e63197SJiri Olsa PT_REGS_OFFSET(PERF_REG_X86_DS, ds), 34c5e63197SJiri Olsa PT_REGS_OFFSET(PERF_REG_X86_ES, es), 35c5e63197SJiri Olsa PT_REGS_OFFSET(PERF_REG_X86_FS, fs), 36c5e63197SJiri Olsa PT_REGS_OFFSET(PERF_REG_X86_GS, gs), 37c5e63197SJiri Olsa #else 38c5e63197SJiri Olsa /* 39c5e63197SJiri Olsa * The pt_regs struct does not store 40c5e63197SJiri Olsa * ds, es, fs, gs in 64 bit mode. 41c5e63197SJiri Olsa */ 42c5e63197SJiri Olsa (unsigned int) -1, 43c5e63197SJiri Olsa (unsigned int) -1, 44c5e63197SJiri Olsa (unsigned int) -1, 45c5e63197SJiri Olsa (unsigned int) -1, 46c5e63197SJiri Olsa #endif 47c5e63197SJiri Olsa #ifdef CONFIG_X86_64 48c5e63197SJiri Olsa PT_REGS_OFFSET(PERF_REG_X86_R8, r8), 49c5e63197SJiri Olsa PT_REGS_OFFSET(PERF_REG_X86_R9, r9), 50c5e63197SJiri Olsa PT_REGS_OFFSET(PERF_REG_X86_R10, r10), 51c5e63197SJiri Olsa PT_REGS_OFFSET(PERF_REG_X86_R11, r11), 52c5e63197SJiri Olsa PT_REGS_OFFSET(PERF_REG_X86_R12, r12), 53c5e63197SJiri Olsa PT_REGS_OFFSET(PERF_REG_X86_R13, r13), 54c5e63197SJiri Olsa PT_REGS_OFFSET(PERF_REG_X86_R14, r14), 55c5e63197SJiri Olsa PT_REGS_OFFSET(PERF_REG_X86_R15, r15), 56c5e63197SJiri Olsa #endif 57c5e63197SJiri Olsa }; 58c5e63197SJiri Olsa 59c5e63197SJiri Olsa u64 perf_reg_value(struct pt_regs *regs, int idx) 60c5e63197SJiri Olsa { 611e6dd8adSDan Carpenter if (WARN_ON_ONCE(idx >= ARRAY_SIZE(pt_regs_offset))) 62c5e63197SJiri Olsa return 0; 63c5e63197SJiri Olsa 64c5e63197SJiri Olsa return regs_get_register(regs, pt_regs_offset[idx]); 65c5e63197SJiri Olsa } 66c5e63197SJiri Olsa 67c5e63197SJiri Olsa #define REG_RESERVED (~((1ULL << PERF_REG_X86_MAX) - 1ULL)) 68c5e63197SJiri Olsa 69c5e63197SJiri Olsa #ifdef CONFIG_X86_32 70c5e63197SJiri Olsa int perf_reg_validate(u64 mask) 71c5e63197SJiri Olsa { 72c5e63197SJiri Olsa if (!mask || mask & REG_RESERVED) 73c5e63197SJiri Olsa return -EINVAL; 74c5e63197SJiri Olsa 75c5e63197SJiri Olsa return 0; 76c5e63197SJiri Olsa } 774018994fSJiri Olsa 784018994fSJiri Olsa u64 perf_reg_abi(struct task_struct *task) 794018994fSJiri Olsa { 804018994fSJiri Olsa return PERF_SAMPLE_REGS_ABI_32; 814018994fSJiri Olsa } 8288a7c26aSAndy Lutomirski 8388a7c26aSAndy Lutomirski void perf_get_regs_user(struct perf_regs *regs_user, 8488a7c26aSAndy Lutomirski struct pt_regs *regs, 8588a7c26aSAndy Lutomirski struct pt_regs *regs_user_copy) 8688a7c26aSAndy Lutomirski { 8788a7c26aSAndy Lutomirski regs_user->regs = task_pt_regs(current); 8888a7c26aSAndy Lutomirski regs_user->abi = perf_reg_abi(current); 8988a7c26aSAndy Lutomirski } 90c5e63197SJiri Olsa #else /* CONFIG_X86_64 */ 91c5e63197SJiri Olsa #define REG_NOSUPPORT ((1ULL << PERF_REG_X86_DS) | \ 92c5e63197SJiri Olsa (1ULL << PERF_REG_X86_ES) | \ 93c5e63197SJiri Olsa (1ULL << PERF_REG_X86_FS) | \ 94c5e63197SJiri Olsa (1ULL << PERF_REG_X86_GS)) 95c5e63197SJiri Olsa 96c5e63197SJiri Olsa int perf_reg_validate(u64 mask) 97c5e63197SJiri Olsa { 98c5e63197SJiri Olsa if (!mask || mask & REG_RESERVED) 99c5e63197SJiri Olsa return -EINVAL; 100c5e63197SJiri Olsa 101c5e63197SJiri Olsa if (mask & REG_NOSUPPORT) 102c5e63197SJiri Olsa return -EINVAL; 103c5e63197SJiri Olsa 104c5e63197SJiri Olsa return 0; 105c5e63197SJiri Olsa } 1064018994fSJiri Olsa 1074018994fSJiri Olsa u64 perf_reg_abi(struct task_struct *task) 1084018994fSJiri Olsa { 1094018994fSJiri Olsa if (test_tsk_thread_flag(task, TIF_IA32)) 1104018994fSJiri Olsa return PERF_SAMPLE_REGS_ABI_32; 1114018994fSJiri Olsa else 1124018994fSJiri Olsa return PERF_SAMPLE_REGS_ABI_64; 1134018994fSJiri Olsa } 11488a7c26aSAndy Lutomirski 11588a7c26aSAndy Lutomirski void perf_get_regs_user(struct perf_regs *regs_user, 11688a7c26aSAndy Lutomirski struct pt_regs *regs, 11788a7c26aSAndy Lutomirski struct pt_regs *regs_user_copy) 11888a7c26aSAndy Lutomirski { 11986c269feSAndy Lutomirski struct pt_regs *user_regs = task_pt_regs(current); 12086c269feSAndy Lutomirski 12186c269feSAndy Lutomirski /* 12286c269feSAndy Lutomirski * If we're in an NMI that interrupted task_pt_regs setup, then 12386c269feSAndy Lutomirski * we can't sample user regs at all. This check isn't really 12486c269feSAndy Lutomirski * sufficient, though, as we could be in an NMI inside an interrupt 12586c269feSAndy Lutomirski * that happened during task_pt_regs setup. 12686c269feSAndy Lutomirski */ 12786c269feSAndy Lutomirski if (regs->sp > (unsigned long)&user_regs->r11 && 12886c269feSAndy Lutomirski regs->sp <= (unsigned long)(user_regs + 1)) { 12986c269feSAndy Lutomirski regs_user->abi = PERF_SAMPLE_REGS_ABI_NONE; 13086c269feSAndy Lutomirski regs_user->regs = NULL; 13186c269feSAndy Lutomirski return; 13286c269feSAndy Lutomirski } 13386c269feSAndy Lutomirski 13486c269feSAndy Lutomirski /* 135aa21df04SDenys Vlasenko * These registers are always saved on 64-bit syscall entry. 136aa21df04SDenys Vlasenko * On 32-bit entry points, they are saved too except r8..r11. 13786c269feSAndy Lutomirski */ 13886c269feSAndy Lutomirski regs_user_copy->ip = user_regs->ip; 1393b75232dSDenys Vlasenko regs_user_copy->ax = user_regs->ax; 14086c269feSAndy Lutomirski regs_user_copy->cx = user_regs->cx; 14186c269feSAndy Lutomirski regs_user_copy->dx = user_regs->dx; 14286c269feSAndy Lutomirski regs_user_copy->si = user_regs->si; 14386c269feSAndy Lutomirski regs_user_copy->di = user_regs->di; 14486c269feSAndy Lutomirski regs_user_copy->r8 = user_regs->r8; 14586c269feSAndy Lutomirski regs_user_copy->r9 = user_regs->r9; 14686c269feSAndy Lutomirski regs_user_copy->r10 = user_regs->r10; 14786c269feSAndy Lutomirski regs_user_copy->r11 = user_regs->r11; 14886c269feSAndy Lutomirski regs_user_copy->orig_ax = user_regs->orig_ax; 14986c269feSAndy Lutomirski regs_user_copy->flags = user_regs->flags; 150aa21df04SDenys Vlasenko regs_user_copy->sp = user_regs->sp; 151aa21df04SDenys Vlasenko regs_user_copy->cs = user_regs->cs; 152aa21df04SDenys Vlasenko regs_user_copy->ss = user_regs->ss; 15386c269feSAndy Lutomirski 15486c269feSAndy Lutomirski /* 155aa21df04SDenys Vlasenko * Most system calls don't save these registers, don't report them. 15686c269feSAndy Lutomirski */ 15786c269feSAndy Lutomirski regs_user_copy->bx = -1; 15886c269feSAndy Lutomirski regs_user_copy->bp = -1; 15986c269feSAndy Lutomirski regs_user_copy->r12 = -1; 16086c269feSAndy Lutomirski regs_user_copy->r13 = -1; 16186c269feSAndy Lutomirski regs_user_copy->r14 = -1; 16286c269feSAndy Lutomirski regs_user_copy->r15 = -1; 16386c269feSAndy Lutomirski 16486c269feSAndy Lutomirski /* 16586c269feSAndy Lutomirski * For this to be at all useful, we need a reasonable guess for 166aa21df04SDenys Vlasenko * the ABI. Be careful: we're in NMI context, and we're 16786c269feSAndy Lutomirski * considering current to be the current task, so we should 16886c269feSAndy Lutomirski * be careful not to look at any other percpu variables that might 16986c269feSAndy Lutomirski * change during context switches. 17086c269feSAndy Lutomirski */ 17186c269feSAndy Lutomirski regs_user->abi = user_64bit_mode(user_regs) ? 17286c269feSAndy Lutomirski PERF_SAMPLE_REGS_ABI_64 : PERF_SAMPLE_REGS_ABI_32; 17386c269feSAndy Lutomirski 17486c269feSAndy Lutomirski regs_user->regs = regs_user_copy; 17588a7c26aSAndy Lutomirski } 176c5e63197SJiri Olsa #endif /* CONFIG_X86_32 */ 177