Commit 03722454 authored by Gao Chen's avatar Gao Chen Committed by guzitao
Browse files

sw64: trace user task unalignment

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



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

It specifies user command to be traced, and records count, address
and PC into debugfs. Note that it can only trace a task with its
command name.

To specify command name and clear old unaligned stat:
	echo something > /sys/kernel/debug/sw64/unaligned

To show unaligned stat:
	cat /sys/kernel/debug/sw64/unaligned

Signed-off-by: default avatarGao Chen <gaochen@wxiat.com>
Reviewed-by: default avatarHe Sheng <hesheng@wxiat.com>
Signed-off-by: default avatarGu Zitao <guzitao@wxiat.com>
parent f92e794d
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -24,4 +24,15 @@
 */
extern struct dentry *sw64_debugfs_dir;

#define UNA_MAX_ENTRIES	64

struct unaligned_stat {
	unsigned long pc;
	unsigned long va;
};

extern char unaligned_task[];
extern unsigned long unaligned_count;
extern struct unaligned_stat unaligned[];

#endif /* _ASM_SW64_DEBUG_H */
+1 −1
Original line number Diff line number Diff line
@@ -30,7 +30,7 @@ obj-$(CONFIG_HIBERNATION) += hibernate_asm.o hibernate.o
obj-$(CONFIG_AUDIT)     += audit.o
obj-$(CONFIG_PCI) += pci_common.o
obj-$(CONFIG_RELOCATABLE)   += relocate.o
obj-$(CONFIG_DEBUG_FS)	+= segvdbg.o
obj-$(CONFIG_DEBUG_FS)	+= segvdbg.o unaligned.o
obj-$(CONFIG_JUMP_LABEL) += jump_label.o

ifeq ($(CONFIG_DEBUG_FS)$(CONFIG_NUMA),yy)
+16 −0
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@
#include <asm/stacktrace.h>
#include <asm/processor.h>
#include <asm/ptrace.h>
#include <asm/debug.h>
#include <asm/efi.h>

#include "proto.h"
@@ -573,6 +574,21 @@ do_entUnaUser(void __user *va, unsigned long opcode,
	unsigned long fp[4];
	unsigned long instr, instr_op, value;

#ifdef CONFIG_DEBUG_FS
	/*
	 * If command name is specified, record some information
	 * to debugfs.
	 */
	if (unaligned_task[0] && !strcmp(unaligned_task, current->comm)) {
		int idx;

		idx = unaligned_count % UNA_MAX_ENTRIES;
		unaligned[idx].va = (unsigned long)va;
		unaligned[idx].pc = regs->pc;
		unaligned_count++;
	}
#endif

	/* Check the UAC bits to decide what the user wants us to do
	 * with the unaliged access.
	 */
+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);