Commit f4d99970 authored by Mao Minkai's avatar Mao Minkai Committed by guzitao
Browse files

sw64: add exception handling support

Sunway inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I8Y8CY



--------------------------------

Add exception handling mechanism for basic SW64 support.

Signed-off-by: default avatarMao Minkai <maominkai@wxiat.com>
Reviewed-by: default avatarHe Sheng <hesheng@wxiat.com>
Signed-off-by: default avatarGu Zitao <guzitao@wxiat.com>
parent fb9fc0ff
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_SW64_KDEBUG_H
#define _ASM_SW64_KDEBUG_H

#include <linux/notifier.h>

enum die_val {
	DIE_OOPS = 1,
	DIE_BREAK,
	DIE_SSTEPBP,
	DIE_UPROBE,
	DIE_UPROBE_XOL,
};

#endif /* _ASM_SW64_KDEBUG_H */
+38 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef _UAPI_ASM_SW64_GENTRAP_H
#define _UAPI_ASM_SW64_GENTRAP_H

/*
 * Definitions for gentrap causes.  They are generated by user-level
 * programs and therefore should be compatible with the corresponding
 * legacy definitions.
 */
#define GEN_INTOVF	-1	/* integer overflow */
#define GEN_INTDIV	-2	/* integer division by zero */
#define GEN_FLTOVF	-3	/* fp overflow */
#define GEN_FLTDIV	-4	/* fp division by zero */
#define GEN_FLTUND	-5	/* fp underflow */
#define GEN_FLTINV	-6	/* invalid fp operand */
#define GEN_FLTINE	-7	/* inexact fp operand */
#define GEN_DECOVF	-8	/* decimal overflow (for COBOL??) */
#define GEN_DECDIV	-9	/* decimal division by zero */
#define GEN_DECINV	-10	/* invalid decimal operand */
#define GEN_ROPRAND	-11	/* reserved operand */
#define GEN_ASSERTERR	-12	/* assertion error */
#define GEN_NULPTRERR	-13	/* null pointer error */
#define GEN_STKOVF	-14	/* stack overflow */
#define GEN_STRLENERR	-15	/* string length error */
#define GEN_SUBSTRERR	-16	/* substring error */
#define GEN_RANGERR	-17	/* range error */
#define GEN_SUBRNG	-18
#define GEN_SUBRNG1	-19
#define GEN_SUBRNG2	-20
#define GEN_SUBRNG3	-21	/* these report range errors for */
#define GEN_SUBRNG4	-22	/* subscripting (indexing) at levels 0..7 */
#define GEN_SUBRNG5	-23
#define GEN_SUBRNG6	-24
#define GEN_SUBRNG7	-25

/* the remaining codes (-26..-1023) are reserved. */

#endif /* _UAPI_ASM_SW64_GENTRAP_H */
+20 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/*
 * include/asm/sysinfo.h
 */

#ifndef _UAPI_ASM_SW64_SYSINFO_H
#define _UAPI_ASM_SW64_SYSINFO_H

#define GSI_IEEE_FP_CONTROL		45

#define SSI_IEEE_FP_CONTROL		14
#define SSI_IEEE_RAISE_EXCEPTION	1001	/* linux specific */

#define UAC_BITMASK			7
#define UAC_NOPRINT			1
#define UAC_NOFIX			2
#define UAC_SIGBUS			4
#define PR_NOFIX			4	/* do not fix up unaligned accesses */

#endif /* _UAPI_ASM_SW64_SYSINFO_H */
+1542 −0

File added.

Preview size limit exceeded, changes collapsed.

+80 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
#include <asm/debug.h>

#include <linux/debugfs.h>
#include <linux/slab.h>
#include <linux/uaccess.h>

unsigned long unaligned_count;
char unaligned_task[TASK_COMM_LEN];
struct unaligned_stat unaligned[UNA_MAX_ENTRIES];

static ssize_t unaligned_set(struct file *file, const char __user *user_buf,
			size_t len, loff_t *ppos)
{
	size_t size;

	unaligned_count = 0;
	size = min(sizeof(unaligned_task), len);
	if (copy_from_user(unaligned_task, user_buf, size))
		return -EFAULT;
	unaligned_task[size - 1] = '\0';

	return len;
}

static int unaligned_show(struct seq_file *m, void *v)
{
	int i, idx, nr;

	if (!unaligned_task[0]) {
		seq_puts(m, "No task traced\n");
		return 0;
	}
	seq_printf(m, "Task command:\t\t%s\n", unaligned_task);
	seq_printf(m, "Unaligned count:\t%ld\n", unaligned_count);
	if (!unaligned_count)
		return 0;
	nr = 0;
	idx = unaligned_count % UNA_MAX_ENTRIES;
	seq_printf(m, "Latest %d unaligned stat:\nNo.\tVA\t\tPC\n", UNA_MAX_ENTRIES);
	if (unaligned_count >= UNA_MAX_ENTRIES) {
		for (i = idx; i < UNA_MAX_ENTRIES; i++)
			seq_printf(m, "%d\t%#lx\t%#lx\n",
					nr++, unaligned[i].va, unaligned[i].pc);
	}
	for (i = 0; i < idx; i++)
		seq_printf(m, "%d\t%#lx\t%#lx\n",
				nr++, unaligned[i].va, unaligned[i].pc);
	return 0;
}

static int unaligned_open(struct inode *inode, struct file *file)
{
	return single_open(file, unaligned_show, NULL);
}

static const struct file_operations unaligned_fops = {
	.read		= seq_read,
	.write		= unaligned_set,
	.open		= unaligned_open,
	.llseek		= default_llseek,
};

static int __init unaligned_init(void)
{
	struct dentry *unaligned;

	if (!sw64_debugfs_dir)
		return -ENODEV;

	unaligned = debugfs_create_file("unaligned", 0644,
			sw64_debugfs_dir, NULL,
			&unaligned_fops);
	if (!unaligned)
		return -ENOMEM;

	return 0;
}

late_initcall(unaligned_init);