Skip to content

Commit

Permalink
Merge git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile
Browse files Browse the repository at this point in the history
Pull arch/tile updates from Chris Metcalf:
 "These are a grab bag of changes to improve debugging and respond to a
  variety of issues raised on LKML over the last couple of months"

* git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile:
  tile: avoid a "label not used" warning in do_page_fault()
  tile: vdso: use raw_read_seqcount_begin() in vdso
  tile: force CONFIG_TILEGX if ARCH != tilepro
  tile: improve stack backtrace
  tile: fix "odd fault" warning for stack backtraces
  tile: set up initial stack top to honor STACK_TOP_DELTA
  tile: support delivering NMIs for multicore backtrace
  drivers/tty/hvc/hvc_tile.c: properly return -EAGAIN
  tile: add <asm/word-at-a-time.h> and enable support functions
  tile: use READ_ONCE() in arch_spin_is_locked()
  tile: modify arch_spin_unlock_wait() semantics
  • Loading branch information
torvalds committed Jul 1, 2015
2 parents 0161b6e + 5316a64 commit 05a8256
Show file tree
Hide file tree
Showing 27 changed files with 402 additions and 254 deletions.
7 changes: 6 additions & 1 deletion arch/tile/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,14 @@ config TILE
select MODULES_USE_ELF_RELA
select HAVE_ARCH_TRACEHOOK
select HAVE_SYSCALL_TRACEPOINTS
select USER_STACKTRACE_SUPPORT
select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
select HAVE_DEBUG_STACKOVERFLOW
select ARCH_WANT_FRAME_POINTERS
select HAVE_CONTEXT_TRACKING
select EDAC_SUPPORT
select GENERIC_STRNCPY_FROM_USER
select GENERIC_STRNLEN_USER

# FIXME: investigate whether we need/want these options.
# select HAVE_IOREMAP_PROT
Expand Down Expand Up @@ -125,8 +128,10 @@ config HVC_TILE
select HVC_IRQ if TILEGX
def_bool y

# Building with ARCH=tilegx (or ARCH=tile) implies using the
# 64-bit TILE-Gx toolchain, so force CONFIG_TILEGX on.
config TILEGX
bool "Building for TILE-Gx (64-bit) processor"
def_bool ARCH != "tilepro"
select SPARSE_IRQ
select GENERIC_IRQ_LEGACY_ALLOC_HWIRQ
select HAVE_FUNCTION_TRACER
Expand Down
5 changes: 5 additions & 0 deletions arch/tile/include/asm/irq.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,9 @@ void tile_irq_activate(unsigned int irq, int tile_irq_type);

void setup_irq_regs(void);

#ifdef __tilegx__
void arch_trigger_all_cpu_backtrace(bool self);
#define arch_trigger_all_cpu_backtrace arch_trigger_all_cpu_backtrace
#endif

#endif /* _ASM_TILE_IRQ_H */
2 changes: 0 additions & 2 deletions arch/tile/include/asm/processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,6 @@ struct thread_struct {
unsigned long long interrupt_mask;
/* User interrupt-control 0 state */
unsigned long intctrl_0;
/* Is this task currently doing a backtrace? */
bool in_backtrace;
/* Any other miscellaneous processor state bits */
unsigned long proc_status;
#if !CHIP_HAS_FIXED_INTVEC_BASE()
Expand Down
6 changes: 5 additions & 1 deletion arch/tile/include/asm/spinlock_32.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,12 @@ static inline int arch_spin_is_locked(arch_spinlock_t *lock)
* to claim the lock is held, since it will be momentarily
* if not already. There's no need to wait for a "valid"
* lock->next_ticket to become available.
* Use READ_ONCE() to ensure that calling this in a loop is OK.
*/
return lock->next_ticket != lock->current_ticket;
int curr = READ_ONCE(lock->current_ticket);
int next = READ_ONCE(lock->next_ticket);

return next != curr;
}

void arch_spin_lock(arch_spinlock_t *lock);
Expand Down
5 changes: 4 additions & 1 deletion arch/tile/include/asm/spinlock_64.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
#ifndef _ASM_TILE_SPINLOCK_64_H
#define _ASM_TILE_SPINLOCK_64_H

#include <linux/compiler.h>

/* Shifts and masks for the various fields in "lock". */
#define __ARCH_SPIN_CURRENT_SHIFT 17
#define __ARCH_SPIN_NEXT_MASK 0x7fff
Expand All @@ -44,7 +46,8 @@ static inline u32 arch_spin_next(u32 val)
/* The lock is locked if a task would have to wait to get it. */
static inline int arch_spin_is_locked(arch_spinlock_t *lock)
{
u32 val = lock->lock;
/* Use READ_ONCE() to ensure that calling this in a loop is OK. */
u32 val = READ_ONCE(lock->lock);
return arch_spin_current(val) != arch_spin_next(val);
}

Expand Down
13 changes: 5 additions & 8 deletions arch/tile/include/asm/stack.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,17 +58,14 @@ extern int KBacktraceIterator_end(struct KBacktraceIterator *kbt);
/* Advance to the next frame. */
extern void KBacktraceIterator_next(struct KBacktraceIterator *kbt);

/* Dump just the contents of the pt_regs structure. */
extern void tile_show_regs(struct pt_regs *);

/*
* Dump stack given complete register info. Use only from the
* architecture-specific code; show_stack()
* and dump_stack() (in entry.S) are architecture-independent entry points.
* and dump_stack() are architecture-independent entry points.
*/
extern void tile_show_stack(struct KBacktraceIterator *, int headers);

/* Dump stack of current process, with registers to seed the backtrace. */
extern void dump_stack_regs(struct pt_regs *);

/* Helper method for assembly dump_stack(). */
extern void _dump_stack(int dummy, ulong pc, ulong lr, ulong sp, ulong r52);
extern void tile_show_stack(struct KBacktraceIterator *);

#endif /* _ASM_TILE_STACK_H */
1 change: 1 addition & 0 deletions arch/tile/include/asm/thread_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ struct thread_info {
unsigned long unalign_jit_tmp[4]; /* temp r0..r3 storage */
void __user *unalign_jit_base; /* unalign fixup JIT base */
#endif
bool in_backtrace; /* currently doing backtrace? */
};

/*
Expand Down
8 changes: 8 additions & 0 deletions arch/tile/include/asm/traps.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,14 @@ void do_timer_interrupt(struct pt_regs *, int fault_num);
/* kernel/messaging.c */
void hv_message_intr(struct pt_regs *, int intnum);

#define TILE_NMI_DUMP_STACK 1 /* Dump stack for sysrq+'l' */

/* kernel/process.c */
void do_nmi_dump_stack(struct pt_regs *regs);

/* kernel/traps.c */
void do_nmi(struct pt_regs *, int fault_num, unsigned long reason);

/* kernel/irq.c */
void tile_dev_intr(struct pt_regs *, int intnum);

Expand Down
66 changes: 10 additions & 56 deletions arch/tile/include/asm/uaccess.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,13 @@ static inline int is_arch_mappable_range(unsigned long addr,
#define is_arch_mappable_range(addr, size) 0
#endif

/*
* Note that using this definition ignores is_arch_mappable_range(),
* so on tilepro code that uses user_addr_max() is constrained not
* to reference the tilepro user-interrupt region.
*/
#define user_addr_max() (current_thread_info()->addr_limit.seg)

/*
* Test whether a block of memory is a valid user space address.
* Returns 0 if the range is valid, nonzero otherwise.
Expand Down Expand Up @@ -471,62 +478,9 @@ copy_in_user(void __user *to, const void __user *from, unsigned long n)
#endif


/**
* strlen_user: - Get the size of a string in user space.
* @str: The string to measure.
*
* Context: User context only. This function may sleep.
*
* Get the size of a NUL-terminated string in user space.
*
* Returns the size of the string INCLUDING the terminating NUL.
* On exception, returns 0.
*
* If there is a limit on the length of a valid string, you may wish to
* consider using strnlen_user() instead.
*/
extern long strnlen_user_asm(const char __user *str, long n);
static inline long __must_check strnlen_user(const char __user *str, long n)
{
might_fault();
return strnlen_user_asm(str, n);
}
#define strlen_user(str) strnlen_user(str, LONG_MAX)

/**
* strncpy_from_user: - Copy a NUL terminated string from userspace, with less checking.
* @dst: Destination address, in kernel space. This buffer must be at
* least @count bytes long.
* @src: Source address, in user space.
* @count: Maximum number of bytes to copy, including the trailing NUL.
*
* Copies a NUL-terminated string from userspace to kernel space.
* Caller must check the specified block with access_ok() before calling
* this function.
*
* On success, returns the length of the string (not including the trailing
* NUL).
*
* If access to userspace fails, returns -EFAULT (some data may have been
* copied).
*
* If @count is smaller than the length of the string, copies @count bytes
* and returns @count.
*/
extern long strncpy_from_user_asm(char *dst, const char __user *src, long);
static inline long __must_check __strncpy_from_user(
char *dst, const char __user *src, long count)
{
might_fault();
return strncpy_from_user_asm(dst, src, count);
}
static inline long __must_check strncpy_from_user(
char *dst, const char __user *src, long count)
{
if (access_ok(VERIFY_READ, src, 1))
return __strncpy_from_user(dst, src, count);
return -EFAULT;
}
extern long strnlen_user(const char __user *str, long n);
extern long strlen_user(const char __user *str);
extern long strncpy_from_user(char *dst, const char __user *src, long);

/**
* clear_user: - Zero a block of memory in user space.
Expand Down
36 changes: 36 additions & 0 deletions arch/tile/include/asm/word-at-a-time.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#ifndef _ASM_WORD_AT_A_TIME_H
#define _ASM_WORD_AT_A_TIME_H

#include <asm/byteorder.h>

struct word_at_a_time { /* unused */ };
#define WORD_AT_A_TIME_CONSTANTS {}

/* Generate 0x01 byte values for non-zero bytes using a SIMD instruction. */
static inline unsigned long has_zero(unsigned long val, unsigned long *data,
const struct word_at_a_time *c)
{
#ifdef __tilegx__
unsigned long mask = __insn_v1cmpeqi(val, 0);
#else /* tilepro */
unsigned long mask = __insn_seqib(val, 0);
#endif
*data = mask;
return mask;
}

/* These operations are both nops. */
#define prep_zero_mask(val, data, c) (data)
#define create_zero_mask(data) (data)

/* And this operation just depends on endianness. */
static inline long find_zero(unsigned long mask)
{
#ifdef __BIG_ENDIAN
return __builtin_clzl(mask) >> 3;
#else
return __builtin_ctzl(mask) >> 3;
#endif
}

#endif /* _ASM_WORD_AT_A_TIME_H */
60 changes: 59 additions & 1 deletion arch/tile/include/hv/hypervisor.h
Original file line number Diff line number Diff line change
Expand Up @@ -321,8 +321,11 @@
/** hv_console_set_ipi */
#define HV_DISPATCH_CONSOLE_SET_IPI 63

/** hv_send_nmi */
#define HV_DISPATCH_SEND_NMI 65

/** One more than the largest dispatch value */
#define _HV_DISPATCH_END 64
#define _HV_DISPATCH_END 66


#ifndef __ASSEMBLER__
Expand Down Expand Up @@ -1253,6 +1256,11 @@ void hv_downcall_dispatch(void);
#define INT_DMATLB_ACCESS_DWNCL INT_DMA_CPL
/** Device interrupt downcall interrupt vector */
#define INT_DEV_INTR_DWNCL INT_WORLD_ACCESS
/** NMI downcall interrupt vector */
#define INT_NMI_DWNCL 64

#define HV_NMI_FLAG_FORCE 0x1 /**< Force an NMI downcall regardless of
the ICS bit of the client. */

#ifndef __ASSEMBLER__

Expand Down Expand Up @@ -1780,6 +1788,56 @@ int hv_dev_poll(int devhdl, __hv32 events, HV_IntArg intarg);
int hv_dev_poll_cancel(int devhdl);


/** NMI information */
typedef struct
{
/** Result: negative error, or HV_NMI_RESULT_xxx. */
int result;

/** PC from interrupted remote core (if result != HV_NMI_RESULT_FAIL_HV). */
HV_VirtAddr pc;

} HV_NMI_Info;

/** NMI issued successfully. */
#define HV_NMI_RESULT_OK 0

/** NMI not issued: remote tile running at client PL with ICS set. */
#define HV_NMI_RESULT_FAIL_ICS 1

/** NMI not issued: remote tile waiting in hypervisor. */
#define HV_NMI_RESULT_FAIL_HV 2

/** Force an NMI downcall regardless of the ICS bit of the client. */
#define HV_NMI_FLAG_FORCE 0x1

/** Send an NMI interrupt request to a particular tile.
*
* This will cause the NMI to be issued on the remote tile regardless
* of the state of the client interrupt mask. However, if the remote
* tile is in the hypervisor, it will not execute the NMI, and
* HV_NMI_RESULT_FAIL_HV will be returned. Similarly, if the remote
* tile is in a client interrupt critical section at the time of the
* NMI, it will not execute the NMI, and HV_NMI_RESULT_FAIL_ICS will
* be returned. In this second case, however, if HV_NMI_FLAG_FORCE
* is set in flags, then the remote tile will enter its NMI interrupt
* vector regardless. Forcing the NMI vector during an interrupt
* critical section will mean that the client can not safely continue
* execution after handling the interrupt.
*
* @param tile Tile to which the NMI request is sent.
* @param info NMI information which is defined by and interpreted by the
* supervisor, is passed to the specified tile, and is
* stored in the SPR register SYSTEM_SAVE_{CLIENT_PL}_2 on the
* specified tile when entering the NMI handler routine.
* Typically, this parameter stores the NMI type, or an aligned
* VA plus some special bits, etc.
* @param flags Flags (HV_NMI_FLAG_xxx).
* @return Information about the requested NMI.
*/
HV_NMI_Info hv_send_nmi(HV_Coord tile, unsigned long info, __hv64 flags);


/** Scatter-gather list for preada/pwritea calls. */
typedef struct
#if CHIP_VA_WIDTH() <= 32
Expand Down
7 changes: 0 additions & 7 deletions arch/tile/kernel/entry.S
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,6 @@ STD_ENTRY(current_text_addr)
{ move r0, lr; jrp lr }
STD_ENDPROC(current_text_addr)

STD_ENTRY(dump_stack)
{ move r2, lr; lnk r1 }
{ move r4, r52; addli r1, r1, dump_stack - . }
{ move r3, sp; j _dump_stack }
jrp lr /* keep backtracer happy */
STD_ENDPROC(dump_stack)

STD_ENTRY(KBacktraceIterator_init_current)
{ move r2, lr; lnk r1 }
{ move r4, r52; addli r1, r1, KBacktraceIterator_init_current - . }
Expand Down
3 changes: 2 additions & 1 deletion arch/tile/kernel/hvglue.S
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,5 @@ gensym hv_flush_all, 0x6e0, 32
gensym hv_get_ipi_pte, 0x700, 32
gensym hv_set_pte_super_shift, 0x720, 32
gensym hv_console_set_ipi, 0x7e0, 32
gensym hv_glue_internals, 0x800, 30720
gensym hv_send_nmi, 0x820, 32
gensym hv_glue_internals, 0x820, 30688
4 changes: 4 additions & 0 deletions arch/tile/kernel/hvglue_trace.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
#define hv_get_ipi_pte _hv_get_ipi_pte
#define hv_set_pte_super_shift _hv_set_pte_super_shift
#define hv_console_set_ipi _hv_console_set_ipi
#define hv_send_nmi _hv_send_nmi
#include <hv/hypervisor.h>
#undef hv_init
#undef hv_install_context
Expand Down Expand Up @@ -134,6 +135,7 @@
#undef hv_get_ipi_pte
#undef hv_set_pte_super_shift
#undef hv_console_set_ipi
#undef hv_send_nmi

/*
* Provide macros based on <linux/syscalls.h> to provide a wrapper
Expand Down Expand Up @@ -264,3 +266,5 @@ HV_WRAP9(int, hv_flush_remote, HV_PhysAddr, cache_pa,
HV_VirtAddr, tlb_va, unsigned long, tlb_length,
unsigned long, tlb_pgsize, unsigned long*, tlb_cpumask,
HV_Remote_ASID*, asids, int, asidcount)
HV_WRAP3(HV_NMI_Info, hv_send_nmi, HV_Coord, tile, unsigned long, info,
__hv64, flags)
6 changes: 6 additions & 0 deletions arch/tile/kernel/intvec_64.S
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,10 @@ intvec_\vecname:
.ifc \c_routine, handle_perf_interrupt
mfspr r2, AUX_PERF_COUNT_STS
.endif
.ifc \c_routine, do_nmi
mfspr r2, SPR_SYSTEM_SAVE_K_2 /* nmi type */
.else
.endif
.endif
.endif
.endif
Expand Down Expand Up @@ -1571,3 +1575,5 @@ intrpt_start:

/* Synthetic interrupt delivered only by the simulator */
int_hand INT_BREAKPOINT, BREAKPOINT, do_breakpoint
/* Synthetic interrupt delivered by hv */
int_hand INT_NMI_DWNCL, NMI_DWNCL, do_nmi, handle_nmi
Loading

0 comments on commit 05a8256

Please sign in to comment.