From: Josh Poimboeuf <[email protected]>

get_segment_base() will be used by the unwind_user code, so make it
global and rename it so it doesn't conflict with a KVM function of the
same name.

As the function is no longer specific to perf, move it to ptrace.c as that
seems to be a better location for a generic function like this.

Signed-off-by: Josh Poimboeuf <[email protected]>
Signed-off-by: Steven Rostedt (Google) <[email protected]>
---
 arch/x86/events/core.c        | 44 ++++-------------------------------
 arch/x86/include/asm/ptrace.h |  2 ++
 arch/x86/kernel/ptrace.c      | 38 ++++++++++++++++++++++++++++++
 3 files changed, 45 insertions(+), 39 deletions(-)

diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c
index 2e10dcf897c5..cc6329235b68 100644
--- a/arch/x86/events/core.c
+++ b/arch/x86/events/core.c
@@ -43,6 +43,7 @@
 #include <asm/ldt.h>
 #include <asm/unwind.h>
 #include <asm/uprobes.h>
+#include <asm/ptrace.h>
 #include <asm/ibt.h>
 
 #include "perf_event.h"
@@ -2809,41 +2810,6 @@ valid_user_frame(const void __user *fp, unsigned long 
size)
        return __access_ok(fp, size);
 }
 
-static unsigned long get_segment_base(unsigned int segment)
-{
-       struct desc_struct *desc;
-       unsigned int idx = segment >> 3;
-
-       if ((segment & SEGMENT_TI_MASK) == SEGMENT_LDT) {
-#ifdef CONFIG_MODIFY_LDT_SYSCALL
-               struct ldt_struct *ldt;
-
-               /*
-                * If we're not in a valid context with a real (not just lazy)
-                * user mm, then don't even try.
-                */
-               if (!nmi_uaccess_okay())
-                       return 0;
-
-               /* IRQs are off, so this synchronizes with smp_store_release */
-               ldt = smp_load_acquire(&current->mm->context.ldt);
-               if (!ldt || idx >= ldt->nr_entries)
-                       return 0;
-
-               desc = &ldt->entries[idx];
-#else
-               return 0;
-#endif
-       } else {
-               if (idx >= GDT_ENTRIES)
-                       return 0;
-
-               desc = raw_cpu_ptr(gdt_page.gdt) + idx;
-       }
-
-       return get_desc_base(desc);
-}
-
 #ifdef CONFIG_UPROBES
 /*
  * Heuristic-based check if uprobe is installed at the function entry.
@@ -2900,8 +2866,8 @@ perf_callchain_user32(struct pt_regs *regs, struct 
perf_callchain_entry_ctx *ent
        if (user_64bit_mode(regs))
                return 0;
 
-       cs_base = get_segment_base(regs->cs);
-       ss_base = get_segment_base(regs->ss);
+       cs_base = segment_base_address(regs->cs);
+       ss_base = segment_base_address(regs->ss);
 
        fp = compat_ptr(ss_base + regs->bp);
        pagefault_disable();
@@ -3020,11 +2986,11 @@ static unsigned long code_segment_base(struct pt_regs 
*regs)
                return 0x10 * regs->cs;
 
        if (user_mode(regs) && regs->cs != __USER_CS)
-               return get_segment_base(regs->cs);
+               return segment_base_address(regs->cs);
 #else
        if (user_mode(regs) && !user_64bit_mode(regs) &&
            regs->cs != __USER32_CS)
-               return get_segment_base(regs->cs);
+               return segment_base_address(regs->cs);
 #endif
        return 0;
 }
diff --git a/arch/x86/include/asm/ptrace.h b/arch/x86/include/asm/ptrace.h
index 50f75467f73d..59357ec98e52 100644
--- a/arch/x86/include/asm/ptrace.h
+++ b/arch/x86/include/asm/ptrace.h
@@ -314,6 +314,8 @@ static __always_inline bool regs_irqs_disabled(struct 
pt_regs *regs)
        return !(regs->flags & X86_EFLAGS_IF);
 }
 
+unsigned long segment_base_address(unsigned int segment);
+
 /* 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);
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
index 095f04bdabdc..81353a09701b 100644
--- a/arch/x86/kernel/ptrace.c
+++ b/arch/x86/kernel/ptrace.c
@@ -41,6 +41,7 @@
 #include <asm/syscall.h>
 #include <asm/fsgsbase.h>
 #include <asm/io_bitmap.h>
+#include <asm/mmu_context.h>
 
 #include "tls.h"
 
@@ -339,6 +340,43 @@ static int set_segment_reg(struct task_struct *task,
 
 #endif /* CONFIG_X86_32 */
 
+unsigned long segment_base_address(unsigned int segment)
+{
+       struct desc_struct *desc;
+       unsigned int idx = segment >> 3;
+
+       lockdep_assert_irqs_disabled();
+
+       if ((segment & SEGMENT_TI_MASK) == SEGMENT_LDT) {
+#ifdef CONFIG_MODIFY_LDT_SYSCALL
+               struct ldt_struct *ldt;
+
+               /*
+                * If we're not in a valid context with a real (not just lazy)
+                * user mm, then don't even try.
+                */
+               if (!nmi_uaccess_okay())
+                       return 0;
+
+               /* IRQs are off, so this synchronizes with smp_store_release */
+               ldt = smp_load_acquire(&current->mm->context.ldt);
+               if (!ldt || idx >= ldt->nr_entries)
+                       return 0;
+
+               desc = &ldt->entries[idx];
+#else
+               return 0;
+#endif
+       } else {
+               if (idx >= GDT_ENTRIES)
+                       return 0;
+
+               desc = raw_cpu_ptr(gdt_page.gdt) + idx;
+       }
+
+       return get_desc_base(desc);
+}
+
 static unsigned long get_flags(struct task_struct *task)
 {
        unsigned long retval = task_pt_regs(task)->flags;
-- 
2.47.2



Reply via email to