Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e225ca27 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull Sparc updates from David Miller:

 1) Updated syscall tracing fix from Al Viro.

 2) SUN4V error reporting was deficient in several areas.

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc:
  sparc64: fix ptrace interaction with force_successful_syscall_return()
  sparc64: Fix deficiencies in sun4v error reporting.
parents 54f7fc25 55c2770e
Loading
Loading
Loading
Loading
+5 −0
Original line number Original line Diff line number Diff line
@@ -265,6 +265,11 @@ extern __must_check long strnlen_user(const char __user *str, long n);
#define __copy_to_user_inatomic ___copy_to_user
#define __copy_to_user_inatomic ___copy_to_user
#define __copy_from_user_inatomic ___copy_from_user
#define __copy_from_user_inatomic ___copy_from_user


struct pt_regs;
extern unsigned long compute_effective_address(struct pt_regs *,
					       unsigned int insn,
					       unsigned int rd);

#endif  /* __ASSEMBLY__ */
#endif  /* __ASSEMBLY__ */


#endif /* _ASM_UACCESS_H */
#endif /* _ASM_UACCESS_H */
+14 −18
Original line number Original line Diff line number Diff line
@@ -212,24 +212,20 @@ linux_sparc_syscall:
3:	stx	%o0, [%sp + PTREGS_OFF + PT_V9_I0]
3:	stx	%o0, [%sp + PTREGS_OFF + PT_V9_I0]
ret_sys_call:
ret_sys_call:
	ldx	[%sp + PTREGS_OFF + PT_V9_TSTATE], %g3
	ldx	[%sp + PTREGS_OFF + PT_V9_TSTATE], %g3
	ldx	[%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc
	sra	%o0, 0, %o0
	sra	%o0, 0, %o0
	mov	%ulo(TSTATE_XCARRY | TSTATE_ICARRY), %g2
	mov	%ulo(TSTATE_XCARRY | TSTATE_ICARRY), %g2
	sllx	%g2, 32, %g2
	sllx	%g2, 32, %g2


	/* Check if force_successful_syscall_return()
	 * was invoked.
	 */
	ldub	[%g6 + TI_SYS_NOERROR], %l2
	brnz,a,pn %l2, 80f
	 stb	%g0, [%g6 + TI_SYS_NOERROR]

	cmp	%o0, -ERESTART_RESTARTBLOCK
	cmp	%o0, -ERESTART_RESTARTBLOCK
	bgeu,pn	%xcc, 1f
	bgeu,pn	%xcc, 1f
	 andcc	%l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %l6
	 andcc	%l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %g0
80:
	ldx	[%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc

2:
	stb	%g0, [%g6 + TI_SYS_NOERROR]
	/* System call success, clear Carry condition code. */
	/* System call success, clear Carry condition code. */
	andn	%g3, %g2, %g3
	andn	%g3, %g2, %g3
3:
	stx	%g3, [%sp + PTREGS_OFF + PT_V9_TSTATE]	
	stx	%g3, [%sp + PTREGS_OFF + PT_V9_TSTATE]	
	bne,pn	%icc, linux_syscall_trace2
	bne,pn	%icc, linux_syscall_trace2
	 add	%l1, 0x4, %l2			! npc = npc+4
	 add	%l1, 0x4, %l2			! npc = npc+4
@@ -238,20 +234,20 @@ ret_sys_call:
	 stx	%l2, [%sp + PTREGS_OFF + PT_V9_TNPC]
	 stx	%l2, [%sp + PTREGS_OFF + PT_V9_TNPC]


1:
1:
	/* Check if force_successful_syscall_return()
	 * was invoked.
	 */
	ldub	[%g6 + TI_SYS_NOERROR], %l2
	brnz,pn %l2, 2b
	 ldx	[%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc
	/* System call failure, set Carry condition code.
	/* System call failure, set Carry condition code.
	 * Also, get abs(errno) to return to the process.
	 * Also, get abs(errno) to return to the process.
	 */
	 */
	andcc	%l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %l6	
	sub	%g0, %o0, %o0
	sub	%g0, %o0, %o0
	or	%g3, %g2, %g3
	stx	%o0, [%sp + PTREGS_OFF + PT_V9_I0]
	stx	%o0, [%sp + PTREGS_OFF + PT_V9_I0]
	stx	%g3, [%sp + PTREGS_OFF + PT_V9_TSTATE]
	ba,pt	%xcc, 3b
	bne,pn	%icc, linux_syscall_trace2
	 or	%g3, %g2, %g3
	 add	%l1, 0x4, %l2			! npc = npc+4
	stx	%l1, [%sp + PTREGS_OFF + PT_V9_TPC]


	b,pt	%xcc, rtrap
	 stx	%l2, [%sp + PTREGS_OFF + PT_V9_TNPC]
linux_syscall_trace2:
linux_syscall_trace2:
	call	syscall_trace_leave
	call	syscall_trace_leave
	 add	%sp, PTREGS_OFF, %o0
	 add	%sp, PTREGS_OFF, %o0
+202 −61
Original line number Original line Diff line number Diff line
/* arch/sparc64/kernel/traps.c
/* arch/sparc64/kernel/traps.c
 *
 *
 * Copyright (C) 1995,1997,2008,2009 David S. Miller (davem@davemloft.net)
 * Copyright (C) 1995,1997,2008,2009,2012 David S. Miller (davem@davemloft.net)
 * Copyright (C) 1997,1999,2000 Jakub Jelinek (jakub@redhat.com)
 * Copyright (C) 1997,1999,2000 Jakub Jelinek (jakub@redhat.com)
 */
 */


@@ -18,6 +18,7 @@
#include <linux/init.h>
#include <linux/init.h>
#include <linux/kdebug.h>
#include <linux/kdebug.h>
#include <linux/ftrace.h>
#include <linux/ftrace.h>
#include <linux/reboot.h>
#include <linux/gfp.h>
#include <linux/gfp.h>


#include <asm/smp.h>
#include <asm/smp.h>
@@ -1760,85 +1761,223 @@ void cheetah_plus_parity_error(int type, struct pt_regs *regs)
}
}


struct sun4v_error_entry {
struct sun4v_error_entry {
	u64		err_handle;
	/* Unique error handle */
	u64		err_stick;
/*0x00*/u64		err_handle;


	u32		err_type;
	/* %stick value at the time of the error */
/*0x08*/u64		err_stick;

/*0x10*/u8		reserved_1[3];

	/* Error type */
/*0x13*/u8		err_type;
#define SUN4V_ERR_TYPE_UNDEFINED	0
#define SUN4V_ERR_TYPE_UNDEFINED	0
#define SUN4V_ERR_TYPE_UNCORRECTED_RES	1
#define SUN4V_ERR_TYPE_UNCORRECTED_RES	1
#define SUN4V_ERR_TYPE_PRECISE_NONRES	2
#define SUN4V_ERR_TYPE_PRECISE_NONRES	2
#define SUN4V_ERR_TYPE_DEFERRED_NONRES	3
#define SUN4V_ERR_TYPE_DEFERRED_NONRES	3
#define SUN4V_ERR_TYPE_WARNING_RES	4
#define SUN4V_ERR_TYPE_SHUTDOWN_RQST	4
#define SUN4V_ERR_TYPE_DUMP_CORE	5
#define SUN4V_ERR_TYPE_SP_STATE_CHANGE	6
#define SUN4V_ERR_TYPE_NUM		7


	u32		err_attrs;
	/* Error attributes */
/*0x14*/u32		err_attrs;
#define SUN4V_ERR_ATTRS_PROCESSOR	0x00000001
#define SUN4V_ERR_ATTRS_PROCESSOR	0x00000001
#define SUN4V_ERR_ATTRS_MEMORY		0x00000002
#define SUN4V_ERR_ATTRS_MEMORY		0x00000002
#define SUN4V_ERR_ATTRS_PIO		0x00000004
#define SUN4V_ERR_ATTRS_PIO		0x00000004
#define SUN4V_ERR_ATTRS_INT_REGISTERS	0x00000008
#define SUN4V_ERR_ATTRS_INT_REGISTERS	0x00000008
#define SUN4V_ERR_ATTRS_FPU_REGISTERS	0x00000010
#define SUN4V_ERR_ATTRS_FPU_REGISTERS	0x00000010
#define SUN4V_ERR_ATTRS_USER_MODE	0x01000000
#define SUN4V_ERR_ATTRS_SHUTDOWN_RQST	0x00000020
#define SUN4V_ERR_ATTRS_PRIV_MODE	0x02000000
#define SUN4V_ERR_ATTRS_ASR		0x00000040
#define SUN4V_ERR_ATTRS_ASI		0x00000080
#define SUN4V_ERR_ATTRS_PRIV_REG	0x00000100
#define SUN4V_ERR_ATTRS_SPSTATE_MSK	0x00000600
#define SUN4V_ERR_ATTRS_SPSTATE_SHFT	9
#define SUN4V_ERR_ATTRS_MODE_MSK	0x03000000
#define SUN4V_ERR_ATTRS_MODE_SHFT	24
#define SUN4V_ERR_ATTRS_RES_QUEUE_FULL	0x80000000
#define SUN4V_ERR_ATTRS_RES_QUEUE_FULL	0x80000000


	u64		err_raddr;
#define SUN4V_ERR_SPSTATE_FAULTED	0
	u32		err_size;
#define SUN4V_ERR_SPSTATE_AVAILABLE	1
	u16		err_cpu;
#define SUN4V_ERR_SPSTATE_NOT_PRESENT	2
	u16		err_pad;

#define SUN4V_ERR_MODE_USER		1
#define SUN4V_ERR_MODE_PRIV		2

	/* Real address of the memory region or PIO transaction */
/*0x18*/u64		err_raddr;

	/* Size of the operation triggering the error, in bytes */
/*0x20*/u32		err_size;

	/* ID of the CPU */
/*0x24*/u16		err_cpu;

	/* Grace periof for shutdown, in seconds */
/*0x26*/u16		err_secs;

	/* Value of the %asi register */
/*0x28*/u8		err_asi;

/*0x29*/u8		reserved_2;

	/* Value of the ASR register number */
/*0x2a*/u16		err_asr;
#define SUN4V_ERR_ASR_VALID		0x8000

/*0x2c*/u32		reserved_3;
/*0x30*/u64		reserved_4;
/*0x38*/u64		reserved_5;
};
};


static atomic_t sun4v_resum_oflow_cnt = ATOMIC_INIT(0);
static atomic_t sun4v_resum_oflow_cnt = ATOMIC_INIT(0);
static atomic_t sun4v_nonresum_oflow_cnt = ATOMIC_INIT(0);
static atomic_t sun4v_nonresum_oflow_cnt = ATOMIC_INIT(0);


static const char *sun4v_err_type_to_str(u32 type)
static const char *sun4v_err_type_to_str(u8 type)
{
{
	switch (type) {
	static const char *types[SUN4V_ERR_TYPE_NUM] = {
	case SUN4V_ERR_TYPE_UNDEFINED:
		"undefined",
		return "undefined";
		"uncorrected resumable",
	case SUN4V_ERR_TYPE_UNCORRECTED_RES:
		"precise nonresumable",
		return "uncorrected resumable";
		"deferred nonresumable",
	case SUN4V_ERR_TYPE_PRECISE_NONRES:
		"shutdown request",
		return "precise nonresumable";
		"dump core",
	case SUN4V_ERR_TYPE_DEFERRED_NONRES:
		"SP state change",
		return "deferred nonresumable";
	};
	case SUN4V_ERR_TYPE_WARNING_RES:

		return "warning resumable";
	if (type < SUN4V_ERR_TYPE_NUM)
	default:
		return types[type];

	return "unknown";
	return "unknown";
}
}

static void sun4v_emit_err_attr_strings(u32 attrs)
{
	static const char *attr_names[] = {
		"processor",
		"memory",
		"PIO",
		"int-registers",
		"fpu-registers",
		"shutdown-request",
		"ASR",
		"ASI",
		"priv-reg",
	};
	static const char *sp_states[] = {
		"sp-faulted",
		"sp-available",
		"sp-not-present",
		"sp-state-reserved",
	};
	static const char *modes[] = {
		"mode-reserved0",
		"user",
		"priv",
		"mode-reserved1",
	};
	u32 sp_state, mode;
	int i;

	for (i = 0; i < ARRAY_SIZE(attr_names); i++) {
		if (attrs & (1U << i)) {
			const char *s = attr_names[i];

			pr_cont("%s ", s);
		}
	}

	sp_state = ((attrs & SUN4V_ERR_ATTRS_SPSTATE_MSK) >>
		    SUN4V_ERR_ATTRS_SPSTATE_SHFT);
	pr_cont("%s ", sp_states[sp_state]);

	mode = ((attrs & SUN4V_ERR_ATTRS_MODE_MSK) >>
		SUN4V_ERR_ATTRS_MODE_SHFT);
	pr_cont("%s ", modes[mode]);

	if (attrs & SUN4V_ERR_ATTRS_RES_QUEUE_FULL)
		pr_cont("res-queue-full ");
}

/* When the report contains a real-address of "-1" it means that the
 * hardware did not provide the address.  So we compute the effective
 * address of the load or store instruction at regs->tpc and report
 * that.  Usually when this happens it's a PIO and in such a case we
 * are using physical addresses with bypass ASIs anyways, so what we
 * report here is exactly what we want.
 */
static void sun4v_report_real_raddr(const char *pfx, struct pt_regs *regs)
{
	unsigned int insn;
	u64 addr;

	if (!(regs->tstate & TSTATE_PRIV))
		return;

	insn = *(unsigned int *) regs->tpc;

	addr = compute_effective_address(regs, insn, 0);

	printk("%s: insn effective address [0x%016llx]\n",
	       pfx, addr);
}
}


static void sun4v_log_error(struct pt_regs *regs, struct sun4v_error_entry *ent, int cpu, const char *pfx, atomic_t *ocnt)
static void sun4v_log_error(struct pt_regs *regs, struct sun4v_error_entry *ent,
			    int cpu, const char *pfx, atomic_t *ocnt)
{
{
	u64 *raw_ptr = (u64 *) ent;
	u32 attrs;
	int cnt;
	int cnt;


	printk("%s: Reporting on cpu %d\n", pfx, cpu);
	printk("%s: Reporting on cpu %d\n", pfx, cpu);
	printk("%s: err_handle[%llx] err_stick[%llx] err_type[%08x:%s]\n",
	printk("%s: TPC [0x%016lx] <%pS>\n",
	       pfx,
	       pfx, regs->tpc, (void *) regs->tpc);
	       ent->err_handle, ent->err_stick,

	       ent->err_type,
	printk("%s: RAW [%016llx:%016llx:%016llx:%016llx\n",
	       sun4v_err_type_to_str(ent->err_type));
	       pfx, raw_ptr[0], raw_ptr[1], raw_ptr[2], raw_ptr[3]);
	printk("%s: err_attrs[%08x:%s %s %s %s %s %s %s %s]\n",
	printk("%s:      %016llx:%016llx:%016llx:%016llx]\n",
	       pfx,
	       pfx, raw_ptr[4], raw_ptr[5], raw_ptr[6], raw_ptr[7]);
	       ent->err_attrs,

	       ((ent->err_attrs & SUN4V_ERR_ATTRS_PROCESSOR) ?
	printk("%s: handle [0x%016llx] stick [0x%016llx]\n",
		"processor" : ""),
	       pfx, ent->err_handle, ent->err_stick);
	       ((ent->err_attrs & SUN4V_ERR_ATTRS_MEMORY) ?

		"memory" : ""),
	printk("%s: type [%s]\n", pfx, sun4v_err_type_to_str(ent->err_type));
	       ((ent->err_attrs & SUN4V_ERR_ATTRS_PIO) ?

		"pio" : ""),
	attrs = ent->err_attrs;
	       ((ent->err_attrs & SUN4V_ERR_ATTRS_INT_REGISTERS) ?
	printk("%s: attrs [0x%08x] < ", pfx, attrs);
		"integer-regs" : ""),
	sun4v_emit_err_attr_strings(attrs);
	       ((ent->err_attrs & SUN4V_ERR_ATTRS_FPU_REGISTERS) ?
	pr_cont(">\n");
		"fpu-regs" : ""),

	       ((ent->err_attrs & SUN4V_ERR_ATTRS_USER_MODE) ?
	/* Various fields in the error report are only valid if
		"user" : ""),
	 * certain attribute bits are set.
	       ((ent->err_attrs & SUN4V_ERR_ATTRS_PRIV_MODE) ?
	 */
		"privileged" : ""),
	if (attrs & (SUN4V_ERR_ATTRS_MEMORY |
	       ((ent->err_attrs & SUN4V_ERR_ATTRS_RES_QUEUE_FULL) ?
		     SUN4V_ERR_ATTRS_PIO |
		"queue-full" : ""));
		     SUN4V_ERR_ATTRS_ASI)) {
	printk("%s: err_raddr[%016llx] err_size[%u] err_cpu[%u]\n",
		printk("%s: raddr [0x%016llx]\n", pfx, ent->err_raddr);
	       pfx,

	       ent->err_raddr, ent->err_size, ent->err_cpu);
		if (ent->err_raddr == ~(u64)0)
			sun4v_report_real_raddr(pfx, regs);
	}

	if (attrs & (SUN4V_ERR_ATTRS_MEMORY | SUN4V_ERR_ATTRS_ASI))
		printk("%s: size [0x%x]\n", pfx, ent->err_size);

	if (attrs & (SUN4V_ERR_ATTRS_PROCESSOR |
		     SUN4V_ERR_ATTRS_INT_REGISTERS |
		     SUN4V_ERR_ATTRS_FPU_REGISTERS |
		     SUN4V_ERR_ATTRS_PRIV_REG))
		printk("%s: cpu[%u]\n", pfx, ent->err_cpu);

	if (attrs & SUN4V_ERR_ATTRS_ASI)
		printk("%s: asi [0x%02x]\n", pfx, ent->err_asi);

	if ((attrs & (SUN4V_ERR_ATTRS_INT_REGISTERS |
		      SUN4V_ERR_ATTRS_FPU_REGISTERS |
		      SUN4V_ERR_ATTRS_PRIV_REG)) &&
	    (ent->err_asr & SUN4V_ERR_ASR_VALID) != 0)
		printk("%s: reg [0x%04x]\n",
		       pfx, ent->err_asr & ~SUN4V_ERR_ASR_VALID);


	show_regs(regs);
	show_regs(regs);


@@ -1874,13 +2013,15 @@ void sun4v_resum_error(struct pt_regs *regs, unsigned long offset)


	put_cpu();
	put_cpu();


	if (ent->err_type == SUN4V_ERR_TYPE_WARNING_RES) {
	if (local_copy.err_type == SUN4V_ERR_TYPE_SHUTDOWN_RQST) {
		/* If err_type is 0x4, it's a powerdown request.  Do
		/* We should really take the seconds field of
		 * not do the usual resumable error log because that
		 * the error report and use it for the shutdown
		 * makes it look like some abnormal error.
		 * invocation, but for now do the same thing we
		 * do for a DS shutdown request.
		 */
		 */
		printk(KERN_INFO "Power down request...\n");
		pr_info("Shutdown request, %u seconds...\n",
		kill_cad_pid(SIGINT, 1);
			local_copy.err_secs);
		orderly_poweroff(true);
		return;
		return;
	}
	}


+0 −2
Original line number Original line Diff line number Diff line
@@ -151,8 +151,6 @@ show_signal_msg(struct pt_regs *regs, int sig, int code,
	printk(KERN_CONT "\n");
	printk(KERN_CONT "\n");
}
}


extern unsigned long compute_effective_address(struct pt_regs *, unsigned int, unsigned int);

static void do_fault_siginfo(int code, int sig, struct pt_regs *regs,
static void do_fault_siginfo(int code, int sig, struct pt_regs *regs,
			     unsigned int insn, int fault_code)
			     unsigned int insn, int fault_code)
{
{