From patchwork Tue Feb 9 05:38:57 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Long X-Patchwork-Id: 61506 Delivered-To: patches@linaro.org Received: by 10.112.43.199 with SMTP id y7csp1843169lbl; Mon, 8 Feb 2016 21:39:04 -0800 (PST) X-Received: by 10.140.93.65 with SMTP id c59mr30116159qge.101.1454996344746; Mon, 08 Feb 2016 21:39:04 -0800 (PST) Return-Path: Received: from mail-qg0-x229.google.com (mail-qg0-x229.google.com. [2607:f8b0:400d:c04::229]) by mx.google.com with ESMTPS id q67si34206713qgd.110.2016.02.08.21.39.04 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 08 Feb 2016 21:39:04 -0800 (PST) Received-SPF: pass (google.com: domain of dave.long@linaro.org designates 2607:f8b0:400d:c04::229 as permitted sender) client-ip=2607:f8b0:400d:c04::229; Authentication-Results: mx.google.com; spf=pass (google.com: domain of dave.long@linaro.org designates 2607:f8b0:400d:c04::229 as permitted sender) smtp.mailfrom=dave.long@linaro.org; dkim=pass header.i=@linaro.org Received: by mail-qg0-x229.google.com with SMTP id b67so46831772qgb.1 for ; Mon, 08 Feb 2016 21:39:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:subject:date:message-id:in-reply-to:references; bh=nJ6ucsskM6mKYjecC3uO5fH2mhBlEC9hckQS5VVcbDs=; b=aKZgHB0HN9677opYYbav/gr75XKQ4iV92VGkZtmP99GJzLljBvXfypdum6BPRKycws q3osXR41+vRNIGI7Jotb4OUjWOTuOW+lYbgBSQ2y9dDmH77VD6/Frd5ZBryAlrVCFatk dCWIAQc+cyh1Js2trALxDZ+6nJHCsZ0P0Lrkg= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references; bh=nJ6ucsskM6mKYjecC3uO5fH2mhBlEC9hckQS5VVcbDs=; b=HekuSIzQvmo25y8hne4jPTfYHD8H9pdTB/BfXgXD1+P4MZ9xA6CFwH52h1LkBbi13a 6s0UY0ISsGNkZtcRvB7VAE2+W+Kj5jMHpNefHR7yQrTi0BqPCIaV2lGlTVDK0sJPvqFU vL1DdMhA4+PEMP3TeLp1DA1PmKcKN1lAAZZkq5LwWK+8goOYLOi6wEt73ZcS7m3HkCvJ zU+VMc8s/XS/Ejoi5icnV9ktDzBZ1BwqS5MWuipVpzmCiBum35ES+kRXXpIKOAZS9Wnf jslULP0a3Uc3Bk1HmbjU0Ydde7QZCTDCQ7qZz1UjK9qhqArPFPogNUZgeKR4JkI3q+/y sAcA== X-Gm-Message-State: AG10YOSMa5sSlY7dFHZfz5AAtKHIpXWMtgMLhCCVqdGQHmK3s8Ley2VFt9aXAKtvQQZlUJc2fbA= X-Received: by 10.140.104.50 with SMTP id z47mr2611156qge.68.1454996344336; Mon, 08 Feb 2016 21:39:04 -0800 (PST) Return-Path: Received: from localhost.localdomain (pool-72-71-243-249.cncdnh.fast00.myfairpoint.net. [72.71.243.249]) by smtp.googlemail.com with ESMTPSA id b135sm15390063qka.2.2016.02.08.21.39.02 (version=TLSv1/SSLv3 cipher=OTHER); Mon, 08 Feb 2016 21:39:03 -0800 (PST) From: David Long To: "H. Peter Anvin" , "chengang@emindsoft.com.cn" , Andy Lutomirski , Benjamin Herrenschmidt , Borislav Petkov , Brian Gerst , David Hildenbrand , Denys Vlasenko , Heiko Carstens , Hendrik Brueckner , Ingo Molnar , Jan Beulich , Kees Cook , Martin Schwidefsky , Michael Ellerman , Oleg Nesterov , Paul Mackerras , Rashmica Gupta , Rich Felker , Richard Kuo , Roland McGrath , Russell King , Thomas Gleixner , Will Deacon , Yoshinori Sato , linux-arm-kernel@lists.infradead.org, linux-hexagon@vger.kernel.org, linux-kernel@vger.kernel.org, linux-s390@vger.kernel.org, linux-sh@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, x86@kernel.org Subject: [PATCH v3 2/2] Consolidate redundant register/stack access code Date: Tue, 9 Feb 2016 00:38:57 -0500 Message-Id: <1454996337-7935-3-git-send-email-dave.long@linaro.org> X-Mailer: git-send-email 2.5.0 In-Reply-To: <1454996337-7935-1-git-send-email-dave.long@linaro.org> References: <1454996337-7935-1-git-send-email-dave.long@linaro.org> From: "David A. Long" Several architectures have identical or functionally equivalent code implementing parts of the HAVE_REGS_AND_STACK_ACCESS_API feature. Move that code out of the architecture directories. Signed-off-by: David A. Long --- arch/arm/include/asm/ptrace.h | 6 --- arch/arm/kernel/ptrace.c | 67 +-------------------------------- arch/hexagon/include/uapi/asm/ptrace.h | 3 -- arch/powerpc/include/asm/ptrace.h | 38 ------------------- arch/powerpc/kernel/ptrace.c | 34 +---------------- arch/s390/include/asm/ptrace.h | 3 -- arch/s390/kernel/ptrace.c | 69 ++++++++++------------------------ arch/sh/include/asm/ptrace.h | 39 ------------------- arch/sh/kernel/Makefile | 2 +- arch/sh/kernel/ptrace.c | 33 ---------------- arch/sh/kernel/ptrace_32.c | 2 +- arch/sh/kernel/ptrace_64.c | 2 +- arch/x86/include/asm/ptrace.h | 37 ------------------ arch/x86/kernel/ptrace.c | 34 +---------------- include/linux/ptrace.h | 42 +++++++++++++++++++++ kernel/ptrace.c | 38 +++++++++++++++++++ 16 files changed, 106 insertions(+), 343 deletions(-) delete mode 100644 arch/sh/kernel/ptrace.c -- 2.5.0 diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h index 51622ba..84a0ea4 100644 --- a/arch/arm/include/asm/ptrace.h +++ b/arch/arm/include/asm/ptrace.h @@ -120,12 +120,6 @@ extern unsigned long profile_pc(struct pt_regs *regs); #include #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 diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index 3b5a2ba..f26e23b 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c @@ -63,7 +63,7 @@ #define REG_OFFSET_NAME(r) \ {.name = #r, .offset = offsetof(struct pt_regs, ARM_##r)} -static const struct pt_regs_offset regoffset_table[] = { +const struct pt_regs_offset regs_offset_table[] = { REG_OFFSET_NAME(r0), REG_OFFSET_NAME(r1), REG_OFFSET_NAME(r2), @@ -85,71 +85,6 @@ static const struct pt_regs_offset regoffset_table[] = { REGS_OFFSET_END, }; -/** - * regs_query_register_offset() - query register offset from its name - * @name: the name of a register - * - * regs_query_register_offset() returns the offset of a register in struct - * pt_regs from its name. If the name is invalid, this returns -EINVAL; - */ -int regs_query_register_offset(const char *name) -{ - const struct pt_regs_offset *roff; - for (roff = regoffset_table; roff->name != NULL; roff++) - if (!strcmp(roff->name, name)) - return roff->offset; - return -EINVAL; -} - -/** - * regs_query_register_name() - query register name from its offset - * @offset: the offset of a register in struct pt_regs. - * - * regs_query_register_name() returns the name of a register from its - * offset in struct pt_regs. If the @offset is invalid, this returns NULL; - */ -const char *regs_query_register_name(unsigned int offset) -{ - const struct pt_regs_offset *roff; - for (roff = regoffset_table; roff->name != NULL; roff++) - if (roff->offset == offset) - return roff->name; - return NULL; -} - -/** - * 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. - */ -bool 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. - */ -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; -} - /* * this routine will get a word off of the processes privileged stack. * the offset is how far from the base addr as stored in the THREAD. diff --git a/arch/hexagon/include/uapi/asm/ptrace.h b/arch/hexagon/include/uapi/asm/ptrace.h index 065e5b3..0afb664 100644 --- a/arch/hexagon/include/uapi/asm/ptrace.h +++ b/arch/hexagon/include/uapi/asm/ptrace.h @@ -29,9 +29,6 @@ #define profile_pc(regs) instruction_pointer(regs) /* kprobe-based event tracer support */ -extern int regs_query_register_offset(const char *name); -extern const char *regs_query_register_name(unsigned int offset); - #define current_pt_regs() \ ((struct pt_regs *) \ ((unsigned long)current_thread_info() + THREAD_SIZE) - 1) diff --git a/arch/powerpc/include/asm/ptrace.h b/arch/powerpc/include/asm/ptrace.h index c0c61fa..64b9b3d 100644 --- a/arch/powerpc/include/asm/ptrace.h +++ b/arch/powerpc/include/asm/ptrace.h @@ -156,8 +156,6 @@ do { \ #include #include -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, dsisr)) /** @@ -177,42 +175,6 @@ static inline unsigned long regs_get_register(struct pt_regs *regs, 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 bool 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; -} - #endif /* __ASSEMBLY__ */ #ifndef __powerpc64__ diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index 77bd4c4..1f8310a 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c @@ -57,7 +57,7 @@ {.name = STR(r##num), .offset = offsetof(struct pt_regs, gpr[num])}, \ {.name = STR(gpr##num), .offset = offsetof(struct pt_regs, gpr[num])} -static const struct pt_regs_offset regoffset_table[] = { +const struct pt_regs_offset regs_offset_table[] = { GPR_OFFSET_NAME(0), GPR_OFFSET_NAME(1), GPR_OFFSET_NAME(2), @@ -107,38 +107,6 @@ static const struct pt_regs_offset regoffset_table[] = { REGS_OFFSET_END, }; -/** - * regs_query_register_offset() - query register offset from its name - * @name: the name of a register - * - * regs_query_register_offset() returns the offset of a register in struct - * pt_regs from its name. If the name is invalid, this returns -EINVAL; - */ -int regs_query_register_offset(const char *name) -{ - const struct pt_regs_offset *roff; - for (roff = regoffset_table; roff->name != NULL; roff++) - if (!strcmp(roff->name, name)) - return roff->offset; - return -EINVAL; -} - -/** - * regs_query_register_name() - query register name from its offset - * @offset: the offset of a register in struct pt_regs. - * - * regs_query_register_name() returns the name of a register from its - * offset in struct pt_regs. If the @offset is invalid, this returns NULL; - */ -const char *regs_query_register_name(unsigned int offset) -{ - const struct pt_regs_offset *roff; - for (roff = regoffset_table; roff->name != NULL; roff++) - if (roff->offset == offset) - return roff->name; - return NULL; -} - /* * does not yet catch signals sent when the child dies. * in exit.c or in signal.c. diff --git a/arch/s390/include/asm/ptrace.h b/arch/s390/include/asm/ptrace.h index 99bc456..890bc54 100644 --- a/arch/s390/include/asm/ptrace.h +++ b/arch/s390/include/asm/ptrace.h @@ -164,10 +164,7 @@ static inline void instruction_pointer_set(struct pt_regs *regs, regs->psw.addr = val; } -int regs_query_register_offset(const char *name); -const char *regs_query_register_name(unsigned int offset); unsigned long regs_get_register(struct pt_regs *regs, unsigned int offset); -unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n); static inline unsigned long kernel_stack_pointer(struct pt_regs *regs) { diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index 49b1c13..8e75a93 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c @@ -1430,9 +1430,26 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task) return &user_s390_view; } -static const char *gpr_names[NUM_GPRS] = { - "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", - "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", +#define REG_OFFSET_NAME(r) {.name = "r" #r, .offset = r} + +const struct pt_regs_offset regs_offset_table[NUM_GPRS+1] = { + REG_OFFSET_NAME(0), + REG_OFFSET_NAME(1), + REG_OFFSET_NAME(2), + REG_OFFSET_NAME(3), + REG_OFFSET_NAME(4), + REG_OFFSET_NAME(5), + REG_OFFSET_NAME(6), + REG_OFFSET_NAME(7), + REG_OFFSET_NAME(8), + REG_OFFSET_NAME(9), + REG_OFFSET_NAME(10), + REG_OFFSET_NAME(11), + REG_OFFSET_NAME(12), + REG_OFFSET_NAME(13), + REG_OFFSET_NAME(14), + REG_OFFSET_NAME(15), + REGS_OFFSET_END }; unsigned long regs_get_register(struct pt_regs *regs, unsigned int offset) @@ -1441,49 +1458,3 @@ unsigned long regs_get_register(struct pt_regs *regs, unsigned int offset) return 0; return regs->gprs[offset]; } - -int regs_query_register_offset(const char *name) -{ - unsigned long offset; - - if (!name || *name != 'r') - return -EINVAL; - if (kstrtoul(name + 1, 10, &offset)) - return -EINVAL; - if (offset >= NUM_GPRS) - return -EINVAL; - return offset; -} - -const char *regs_query_register_name(unsigned int offset) -{ - if (offset >= NUM_GPRS) - return NULL; - return gpr_names[offset]; -} - -static int regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr) -{ - unsigned long ksp = kernel_stack_pointer(regs); - - return (addr & ~(THREAD_SIZE - 1)) == (ksp & ~(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 specifined by @regs. If the @n th entry is NOT in the kernel stack, - * this returns 0. - */ -unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n) -{ - unsigned long addr; - - addr = kernel_stack_pointer(regs) + n * sizeof(long); - if (!regs_within_kernel_stack(regs, addr)) - return 0; - return *(unsigned long *)addr; -} diff --git a/arch/sh/include/asm/ptrace.h b/arch/sh/include/asm/ptrace.h index 523955f..8045eb4 100644 --- a/arch/sh/include/asm/ptrace.h +++ b/arch/sh/include/asm/ptrace.h @@ -29,10 +29,6 @@ {.name = __stringify(tr##num), .offset = offsetof(struct pt_regs, tregs[num])} /* 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); - -extern const struct pt_regs_offset regoffset_table[]; /** * regs_get_register() - get register value from its offset @@ -51,41 +47,6 @@ static inline unsigned long regs_get_register(struct pt_regs *regs, 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; -} - struct perf_event; struct perf_sample_data; diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile index 2ccf36c..4ae9a11 100644 --- a/arch/sh/kernel/Makefile +++ b/arch/sh/kernel/Makefile @@ -14,7 +14,7 @@ CFLAGS_REMOVE_return_address.o = -pg obj-y := debugtraps.o dma-nommu.o dumpstack.o \ idle.o io.o irq.o irq_$(BITS).o kdebugfs.o \ machvec.o nmi_debug.o process.o \ - process_$(BITS).o ptrace.o ptrace_$(BITS).o \ + process_$(BITS).o ptrace_$(BITS).o \ reboot.o return_address.o \ setup.o signal_$(BITS).o sys_sh.o \ syscalls_$(BITS).o time.o topology.o traps.o \ diff --git a/arch/sh/kernel/ptrace.c b/arch/sh/kernel/ptrace.c deleted file mode 100644 index 0a05983..0000000 --- a/arch/sh/kernel/ptrace.c +++ /dev/null @@ -1,33 +0,0 @@ -#include - -/** - * regs_query_register_offset() - query register offset from its name - * @name: the name of a register - * - * regs_query_register_offset() returns the offset of a register in struct - * pt_regs from its name. If the name is invalid, this returns -EINVAL; - */ -int regs_query_register_offset(const char *name) -{ - const struct pt_regs_offset *roff; - for (roff = regoffset_table; roff->name != NULL; roff++) - if (!strcmp(roff->name, name)) - return roff->offset; - return -EINVAL; -} - -/** - * regs_query_register_name() - query register name from its offset - * @offset: the offset of a register in struct pt_regs. - * - * regs_query_register_name() returns the name of a register from its - * offset in struct pt_regs. If the @offset is invalid, this returns NULL; - */ -const char *regs_query_register_name(unsigned int offset) -{ - const struct pt_regs_offset *roff; - for (roff = regoffset_table; roff->name != NULL; roff++) - if (roff->offset == offset) - return roff->name; - return NULL; -} diff --git a/arch/sh/kernel/ptrace_32.c b/arch/sh/kernel/ptrace_32.c index e6fe4f4..c5c385c 100644 --- a/arch/sh/kernel/ptrace_32.c +++ b/arch/sh/kernel/ptrace_32.c @@ -276,7 +276,7 @@ static int dspregs_active(struct task_struct *target, } #endif -const struct pt_regs_offset regoffset_table[] = { +const struct pt_regs_offset regs_offset_table[] = { REG_OFFSET_NAME(0), REG_OFFSET_NAME(1), REG_OFFSET_NAME(2), diff --git a/arch/sh/kernel/ptrace_64.c b/arch/sh/kernel/ptrace_64.c index af55bb6..565227ef 100644 --- a/arch/sh/kernel/ptrace_64.c +++ b/arch/sh/kernel/ptrace_64.c @@ -252,7 +252,7 @@ static int fpregs_active(struct task_struct *target, } #endif -const struct pt_regs_offset regoffset_table[] = { +const struct pt_regs_offset regs_offset_table[] = { REGS_OFFSET_NAME(pc), REGS_OFFSET_NAME(sr), REGS_OFFSET_NAME(syscall_nr), diff --git a/arch/x86/include/asm/ptrace.h b/arch/x86/include/asm/ptrace.h index 6271281..0f498ff 100644 --- a/arch/x86/include/asm/ptrace.h +++ b/arch/x86/include/asm/ptrace.h @@ -156,8 +156,6 @@ static inline unsigned long kernel_stack_pointer(struct pt_regs *regs) #include /* 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)) /** @@ -186,41 +184,6 @@ static inline unsigned long regs_get_register(struct pt_regs *regs, 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; -} - #define arch_has_single_step() (1) #ifdef CONFIG_X86_DEBUGCTLMSR #define arch_has_block_step() (1) diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index ff3314f..e380e3d 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c @@ -52,7 +52,7 @@ enum x86_regset { }; -static const struct pt_regs_offset regoffset_table[] = { +const struct pt_regs_offset regs_offset_table[] = { #ifdef CONFIG_X86_64 REGS_OFFSET_NAME(r15), REGS_OFFSET_NAME(r14), @@ -85,38 +85,6 @@ static const struct pt_regs_offset regoffset_table[] = { REGS_OFFSET_END, }; -/** - * regs_query_register_offset() - query register offset from its name - * @name: the name of a register - * - * regs_query_register_offset() returns the offset of a register in struct - * pt_regs from its name. If the name is invalid, this returns -EINVAL; - */ -int regs_query_register_offset(const char *name) -{ - const struct pt_regs_offset *roff; - for (roff = regoffset_table; roff->name != NULL; roff++) - if (!strcmp(roff->name, name)) - return roff->offset; - return -EINVAL; -} - -/** - * regs_query_register_name() - query register name from its offset - * @offset: the offset of a register in struct pt_regs. - * - * regs_query_register_name() returns the name of a register from its - * offset in struct pt_regs. If the @offset is invalid, this returns NULL; - */ -const char *regs_query_register_name(unsigned int offset) -{ - const struct pt_regs_offset *roff; - for (roff = regoffset_table; roff->name != NULL; roff++) - if (roff->offset == offset) - return roff->name; - return NULL; -} - /* * does not yet catch signals sent when the child dies. * in exit.c or in signal.c. diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h index 4e1c6fd..08423b0 100644 --- a/include/linux/ptrace.h +++ b/include/linux/ptrace.h @@ -416,6 +416,48 @@ struct pt_regs_offset { int offset; }; +extern const struct pt_regs_offset regs_offset_table[]; + +extern int regs_query_register_offset(const char *name); +extern const char *regs_query_register_name(unsigned int 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 bool 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; +} + #endif /* CONFIG_HAVE_REGS_AND_STACK_ACCESS_API */ #endif diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 2341efe..f657018 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -1264,3 +1264,41 @@ COMPAT_SYSCALL_DEFINE4(ptrace, compat_long_t, request, compat_long_t, pid, return ret; } #endif /* CONFIG_COMPAT */ + +#ifdef CONFIG_HAVE_REGS_AND_STACK_ACCESS_API + +/** + * regs_query_register_offset() - query register offset from its name + * @name: the name of a register + * + * regs_query_register_offset() returns the offset of a register in struct + * pt_regs from its name. If the name is invalid, this returns -EINVAL; + */ +int regs_query_register_offset(const char *name) +{ + const struct pt_regs_offset *roff; + + for (roff = regs_offset_table; roff->name != NULL; roff++) + if (!strcmp(roff->name, name)) + return roff->offset; + return -EINVAL; +} + +/** + * regs_query_register_name() - query register name from its offset + * @offset: the offset of a register in struct pt_regs. + * + * regs_query_register_name() returns the name of a register from its + * offset in struct pt_regs. If the @offset is invalid, this returns NULL; + */ +const char *regs_query_register_name(unsigned int offset) +{ + const struct pt_regs_offset *roff; + + for (roff = regs_offset_table; roff->name != NULL; roff++) + if (roff->offset == offset) + return roff->name; + return NULL; +} + +#endif /* CONFIG_HAVE_REGS_AND_STACK_ACCESS_API */