You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
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:
@@ -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 */
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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? */
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 */
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user