Merge git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile

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
This commit is contained in:
Linus Torvalds
2015-06-30 21:47:12 -07:00
27 changed files with 404 additions and 256 deletions
+5
View File
@@ -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
View File
@@ -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()
+5 -1
View File
@@ -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);
+4 -1
View File
@@ -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
@@ -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);
}
+5 -8
View File
@@ -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
View File
@@ -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? */
};
/*
+8
View File
@@ -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);
+10 -56
View File
@@ -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.
@@ -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.
+36
View File
@@ -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 */
+59 -1
View File
@@ -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__
@@ -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__
@@ -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