Skip to content

Commit

Permalink
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc
Browse files Browse the repository at this point in the history
Pull sparc updates from David Miller:
 "Just a bunch of small cleanups and fixes here, and support for user
  probes from Allen Pais"

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc:
  sparc: fix a building error reported by kbuild
  sparc64: fix typo in pgd_clear()
  sparc64: restore irq in error paths in iommu
  sparc: leon: Fix a retry loop in leon_init_timers()
  sparc64: make string buffers large enough
  sparc64: move dereference after check for NULL
  sparc: kernel: use builtin_platform_driver
  sparc64:Support User Probes for sparc
  • Loading branch information
Linus Torvalds committed Dec 12, 2016
2 parents ce38aa9 + 541cc39 commit 067d14f
Show file tree
Hide file tree
Showing 20 changed files with 537 additions and 44 deletions.
1 change: 1 addition & 0 deletions arch/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ config KPROBES_ON_FTRACE

config UPROBES
def_bool n
depends on ARCH_SUPPORTS_UPROBES
help
Uprobes is the user-space counterpart to kprobes: they
enable instrumentation applications (such as 'perf probe')
Expand Down
3 changes: 3 additions & 0 deletions arch/sparc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,9 @@ config PGTABLE_LEVELS
default 4 if 64BIT
default 3

config ARCH_SUPPORTS_UPROBES
def_bool y if SPARC64

source "init/Kconfig"

source "kernel/Kconfig.freezer"
Expand Down
1 change: 1 addition & 0 deletions arch/sparc/configs/sparc64_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ CONFIG_SCHEDSTATS=y
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_BLK_DEV_IO_TRACE=y
CONFIG_UPROBE_EVENTS=y
CONFIG_KEYS=y
CONFIG_CRYPTO_NULL=m
CONFIG_CRYPTO_TEST=m
Expand Down
2 changes: 2 additions & 0 deletions arch/sparc/include/asm/kdebug_64.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ enum die_val {
DIE_OOPS = 1,
DIE_DEBUG, /* ta 0x70 */
DIE_DEBUG_2, /* ta 0x71 */
DIE_BPT, /* ta 0x73 */
DIE_SSTEP, /* ta 0x74 */
DIE_DIE,
DIE_TRAP,
DIE_TRAP_TL1,
Expand Down
2 changes: 1 addition & 1 deletion arch/sparc/include/asm/pgtable_64.h
Original file line number Diff line number Diff line change
Expand Up @@ -826,7 +826,7 @@ static inline unsigned long __pmd_page(pmd_t pmd)
#define pgd_page_vaddr(pgd) \
((unsigned long) __va(pgd_val(pgd)))
#define pgd_present(pgd) (pgd_val(pgd) != 0U)
#define pgd_clear(pgdp) (pgd_val(*(pgd)) = 0UL)
#define pgd_clear(pgdp) (pgd_val(*(pgdp)) = 0UL)

static inline unsigned long pud_large(pud_t pud)
{
Expand Down
35 changes: 34 additions & 1 deletion arch/sparc/include/asm/ptrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,10 @@ extern union global_cpu_snapshot global_cpu_snapshot[NR_CPUS];
#define force_successful_syscall_return() set_thread_noerror(1)
#define user_mode(regs) (!((regs)->tstate & TSTATE_PRIV))
#define instruction_pointer(regs) ((regs)->tpc)
#define instruction_pointer_set(regs, val) ((regs)->tpc = (val))
#define instruction_pointer_set(regs, val) do { \
(regs)->tpc = (val); \
(regs)->tnpc = (val)+4; \
} while (0)
#define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP])
static inline int is_syscall_success(struct pt_regs *regs)
{
Expand All @@ -77,6 +80,36 @@ unsigned long profile_pc(struct pt_regs *);
#else
#define profile_pc(regs) instruction_pointer(regs)
#endif

#define MAX_REG_OFFSET (offsetof(struct pt_regs, magic))

extern int regs_query_register_offset(const char *name);

/**
* 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 long offset)
{
if (unlikely(offset >= MAX_REG_OFFSET))
return 0;
if (offset == PT_V9_Y)
return *(unsigned int *)((unsigned long)regs + offset);
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->u_regs[UREG_I6];
}
#else /* __ASSEMBLY__ */
#endif /* __ASSEMBLY__ */
#else /* (defined(__sparc__) && defined(__arch64__)) */
Expand Down
6 changes: 4 additions & 2 deletions arch/sparc/include/asm/thread_info_64.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ register struct thread_info *current_thread_info_reg asm("g6");
#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
/* flag bit 4 is available */
#define TIF_UNALIGNED 5 /* allowed to do unaligned accesses */
/* flag bit 6 is available */
#define TIF_UPROBE 6 /* breakpointed or singlestepped */
#define TIF_32BIT 7 /* 32-bit binary */
#define TIF_NOHZ 8 /* in adaptive nohz mode */
#define TIF_SECCOMP 9 /* secure computing */
Expand All @@ -199,6 +199,7 @@ register struct thread_info *current_thread_info_reg asm("g6");
#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
#define _TIF_UNALIGNED (1<<TIF_UNALIGNED)
#define _TIF_UPROBE (1<<TIF_UPROBE)
#define _TIF_32BIT (1<<TIF_32BIT)
#define _TIF_NOHZ (1<<TIF_NOHZ)
#define _TIF_SECCOMP (1<<TIF_SECCOMP)
Expand All @@ -209,7 +210,8 @@ register struct thread_info *current_thread_info_reg asm("g6");
#define _TIF_USER_WORK_MASK ((0xff << TI_FLAG_WSAVED_SHIFT) | \
_TIF_DO_NOTIFY_RESUME_MASK | \
_TIF_NEED_RESCHED)
#define _TIF_DO_NOTIFY_RESUME_MASK (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING)
#define _TIF_DO_NOTIFY_RESUME_MASK (_TIF_NOTIFY_RESUME | \
_TIF_SIGPENDING | _TIF_UPROBE)

#define is_32bit_task() (test_thread_flag(TIF_32BIT))

Expand Down
1 change: 1 addition & 0 deletions arch/sparc/include/asm/topology_64.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#ifdef CONFIG_NUMA

#include <asm/mmzone.h>
#include <asm/cpudata.h>

static inline int cpu_to_node(int cpu)
{
Expand Down
6 changes: 6 additions & 0 deletions arch/sparc/include/asm/ttable.h
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,12 @@
#define KPROBES_TRAP(lvl) TRAP_ARG(bad_trap, lvl)
#endif

#ifdef CONFIG_UPROBES
#define UPROBES_TRAP(lvl) TRAP_ARG(uprobe_trap, lvl)
#else
#define UPROBES_TRAP(lvl) TRAP_ARG(bad_trap, lvl)
#endif

#ifdef CONFIG_KGDB
#define KGDB_TRAP(lvl) TRAP_IRQ(kgdb_trap, lvl)
#else
Expand Down
59 changes: 59 additions & 0 deletions arch/sparc/include/asm/uprobes.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#ifndef _ASM_UPROBES_H
#define _ASM_UPROBES_H
/*
* User-space Probes (UProbes) for sparc
*
* Copyright (C) 2013 Oracle, Inc.
*
* 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, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Jose E. Marchesi <jose.marchesi@oracle.com>
* Eric Saint Etienne <eric.saint.etienne@oracle.com>
*/

typedef u32 uprobe_opcode_t;

#define MAX_UINSN_BYTES 4
#define UPROBE_XOL_SLOT_BYTES (MAX_UINSN_BYTES * 2)

#define UPROBE_SWBP_INSN_SIZE 4
#define UPROBE_SWBP_INSN 0x91d02073 /* ta 0x73 */
#define UPROBE_STP_INSN 0x91d02074 /* ta 0x74 */

#define ANNUL_BIT (1 << 29)

struct arch_uprobe {
union {
u8 insn[MAX_UINSN_BYTES];
u32 ixol;
};
};

struct arch_uprobe_task {
u32 saved_tpc;
u32 saved_tnpc;
};

struct task_struct;
struct notifier_block;

extern int arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long addr);
extern int arch_uprobe_pre_xol(struct arch_uprobe *aup, struct pt_regs *regs);
extern int arch_uprobe_post_xol(struct arch_uprobe *aup, struct pt_regs *regs);
extern bool arch_uprobe_xol_was_trapped(struct task_struct *tsk);
extern int arch_uprobe_exception_notify(struct notifier_block *self, unsigned long val, void *data);
extern void arch_uprobe_abort_xol(struct arch_uprobe *aup, struct pt_regs *regs);

#endif /* _ASM_UPROBES_H */
1 change: 1 addition & 0 deletions arch/sparc/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,5 @@ obj-$(CONFIG_COMPAT) += $(audit--y)
pc--$(CONFIG_PERF_EVENTS) := perf_event.o
obj-$(CONFIG_SPARC64) += $(pc--y)

obj-$(CONFIG_UPROBES) += uprobes.o
obj-$(CONFIG_SPARC64) += jump_label.o
56 changes: 28 additions & 28 deletions arch/sparc/kernel/leon_kernel.c
Original file line number Diff line number Diff line change
Expand Up @@ -349,37 +349,37 @@ void __init leon_init_timers(void)

/* Find GPTIMER Timer Registers base address otherwise bail out. */
nnp = rootnp;
do {
np = of_find_node_by_name(nnp, "GAISLER_GPTIMER");
if (!np) {
np = of_find_node_by_name(nnp, "01_011");
if (!np)
goto bad;
}

ampopts = 0;
pp = of_find_property(np, "ampopts", &len);
if (pp) {
ampopts = *(int *)pp->value;
if (ampopts == 0) {
/* Skip this instance, resource already
* allocated by other OS */
nnp = np;
continue;
}
retry:
np = of_find_node_by_name(nnp, "GAISLER_GPTIMER");
if (!np) {
np = of_find_node_by_name(nnp, "01_011");
if (!np)
goto bad;
}

ampopts = 0;
pp = of_find_property(np, "ampopts", &len);
if (pp) {
ampopts = *(int *)pp->value;
if (ampopts == 0) {
/* Skip this instance, resource already
* allocated by other OS */
nnp = np;
goto retry;
}
}

/* Select Timer-Instance on Timer Core. Default is zero */
leon3_gptimer_idx = ampopts & 0x7;

/* Select Timer-Instance on Timer Core. Default is zero */
leon3_gptimer_idx = ampopts & 0x7;

pp = of_find_property(np, "reg", &len);
if (pp)
leon3_gptimer_regs = *(struct leon3_gptimer_regs_map **)
pp->value;
pp = of_find_property(np, "interrupts", &len);
if (pp)
leon3_gptimer_irq = *(unsigned int *)pp->value;
} while (0);
pp = of_find_property(np, "reg", &len);
if (pp)
leon3_gptimer_regs = *(struct leon3_gptimer_regs_map **)
pp->value;
pp = of_find_property(np, "interrupts", &len);
if (pp)
leon3_gptimer_irq = *(unsigned int *)pp->value;

if (!(leon3_gptimer_regs && leon3_irqctrl_regs && leon3_gptimer_irq))
goto bad;
Expand Down
7 changes: 4 additions & 3 deletions arch/sparc/kernel/pci_sun4v.c
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ static void *dma_4v_alloc_coherent(struct device *dev, size_t size,
return ret;

iommu_map_fail:
local_irq_restore(flags);
iommu_tbl_range_free(tbl, *dma_addrp, npages, IOMMU_ERROR_CODE);

range_alloc_fail:
Expand Down Expand Up @@ -414,6 +415,7 @@ static dma_addr_t dma_4v_map_page(struct device *dev, struct page *page,
return DMA_ERROR_CODE;

iommu_map_fail:
local_irq_restore(flags);
iommu_tbl_range_free(tbl, bus_addr, npages, IOMMU_ERROR_CODE);
return DMA_ERROR_CODE;
}
Expand Down Expand Up @@ -478,11 +480,10 @@ static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist,
BUG_ON(direction == DMA_NONE);

iommu = dev->archdata.iommu;
atu = iommu->atu;

if (nelems == 0 || !iommu)
return 0;

atu = iommu->atu;

prot = HV_PCI_MAP_ATTR_READ;
if (direction != DMA_TO_DEVICE)
prot |= HV_PCI_MAP_ATTR_WRITE;
Expand Down
7 changes: 1 addition & 6 deletions arch/sparc/kernel/power.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,4 @@ static struct platform_driver power_driver = {
},
};

static int __init power_init(void)
{
return platform_driver_register(&power_driver);
}

device_initcall(power_init);
builtin_platform_driver(power_driver);
54 changes: 54 additions & 0 deletions arch/sparc/kernel/ptrace_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,43 @@

/* #define ALLOW_INIT_TRACING */

struct pt_regs_offset {
const char *name;
int offset;
};

#define REG_OFFSET_NAME(n, r) \
{.name = n, .offset = (PT_V9_##r)}
#define REG_OFFSET_END {.name = NULL, .offset = 0}

static const struct pt_regs_offset regoffset_table[] = {
REG_OFFSET_NAME("g0", G0),
REG_OFFSET_NAME("g1", G1),
REG_OFFSET_NAME("g2", G2),
REG_OFFSET_NAME("g3", G3),
REG_OFFSET_NAME("g4", G4),
REG_OFFSET_NAME("g5", G5),
REG_OFFSET_NAME("g6", G6),
REG_OFFSET_NAME("g7", G7),

REG_OFFSET_NAME("i0", I0),
REG_OFFSET_NAME("i1", I1),
REG_OFFSET_NAME("i2", I2),
REG_OFFSET_NAME("i3", I3),
REG_OFFSET_NAME("i4", I4),
REG_OFFSET_NAME("i5", I5),
REG_OFFSET_NAME("i6", I6),
REG_OFFSET_NAME("i7", I7),

REG_OFFSET_NAME("tstate", TSTATE),
REG_OFFSET_NAME("pc", TPC),
REG_OFFSET_NAME("npc", TNPC),
REG_OFFSET_NAME("y", Y),
REG_OFFSET_NAME("lr", I7),

REG_OFFSET_END,
};

/*
* Called by kernel/ptrace.c when detaching..
*
Expand Down Expand Up @@ -1107,3 +1144,20 @@ asmlinkage void syscall_trace_leave(struct pt_regs *regs)
if (test_thread_flag(TIF_NOHZ))
user_enter();
}

/**
* 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;
}
2 changes: 2 additions & 0 deletions arch/sparc/kernel/signal_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,8 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, unsigned long thread_info_flags)
{
user_exit();
if (thread_info_flags & _TIF_UPROBE)
uprobe_notify_resume(regs);
if (thread_info_flags & _TIF_SIGPENDING)
do_signal(regs, orig_i0);
if (thread_info_flags & _TIF_NOTIFY_RESUME) {
Expand Down
Loading

0 comments on commit 067d14f

Please sign in to comment.