xref: /openbmc/linux/arch/loongarch/kernel/sysrq.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
1dea2df3cSHuacai Chen // SPDX-License-Identifier: GPL-2.0
2dea2df3cSHuacai Chen /*
3dea2df3cSHuacai Chen  * LoongArch specific sysrq operations.
4dea2df3cSHuacai Chen  *
5dea2df3cSHuacai Chen  * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
6dea2df3cSHuacai Chen  */
7dea2df3cSHuacai Chen #include <linux/init.h>
8dea2df3cSHuacai Chen #include <linux/smp.h>
9dea2df3cSHuacai Chen #include <linux/spinlock.h>
10dea2df3cSHuacai Chen #include <linux/sysrq.h>
11dea2df3cSHuacai Chen #include <linux/workqueue.h>
12dea2df3cSHuacai Chen 
13dea2df3cSHuacai Chen #include <asm/cpu-features.h>
14dea2df3cSHuacai Chen #include <asm/tlb.h>
15dea2df3cSHuacai Chen 
16dea2df3cSHuacai Chen /*
17dea2df3cSHuacai Chen  * Dump TLB entries on all CPUs.
18dea2df3cSHuacai Chen  */
19dea2df3cSHuacai Chen 
20dea2df3cSHuacai Chen static DEFINE_SPINLOCK(show_lock);
21dea2df3cSHuacai Chen 
sysrq_tlbdump_single(void * dummy)22dea2df3cSHuacai Chen static void sysrq_tlbdump_single(void *dummy)
23dea2df3cSHuacai Chen {
24dea2df3cSHuacai Chen 	unsigned long flags;
25dea2df3cSHuacai Chen 
26dea2df3cSHuacai Chen 	spin_lock_irqsave(&show_lock, flags);
27dea2df3cSHuacai Chen 
28dea2df3cSHuacai Chen 	pr_info("CPU%d:\n", smp_processor_id());
29dea2df3cSHuacai Chen 	dump_tlb_regs();
30dea2df3cSHuacai Chen 	pr_info("\n");
31dea2df3cSHuacai Chen 	dump_tlb_all();
32dea2df3cSHuacai Chen 	pr_info("\n");
33dea2df3cSHuacai Chen 
34dea2df3cSHuacai Chen 	spin_unlock_irqrestore(&show_lock, flags);
35dea2df3cSHuacai Chen }
36dea2df3cSHuacai Chen 
37dea2df3cSHuacai Chen #ifdef CONFIG_SMP
sysrq_tlbdump_othercpus(struct work_struct * dummy)38dea2df3cSHuacai Chen static void sysrq_tlbdump_othercpus(struct work_struct *dummy)
39dea2df3cSHuacai Chen {
40dea2df3cSHuacai Chen 	smp_call_function(sysrq_tlbdump_single, NULL, 0);
41dea2df3cSHuacai Chen }
42dea2df3cSHuacai Chen 
43dea2df3cSHuacai Chen static DECLARE_WORK(sysrq_tlbdump, sysrq_tlbdump_othercpus);
44dea2df3cSHuacai Chen #endif
45dea2df3cSHuacai Chen 
sysrq_handle_tlbdump(u8 key)46*bcb48185SJiri Slaby static void sysrq_handle_tlbdump(u8 key)
47dea2df3cSHuacai Chen {
48dea2df3cSHuacai Chen 	sysrq_tlbdump_single(NULL);
49dea2df3cSHuacai Chen #ifdef CONFIG_SMP
50dea2df3cSHuacai Chen 	schedule_work(&sysrq_tlbdump);
51dea2df3cSHuacai Chen #endif
52dea2df3cSHuacai Chen }
53dea2df3cSHuacai Chen 
54dea2df3cSHuacai Chen static struct sysrq_key_op sysrq_tlbdump_op = {
55dea2df3cSHuacai Chen 	.handler        = sysrq_handle_tlbdump,
56dea2df3cSHuacai Chen 	.help_msg       = "show-tlbs(x)",
57dea2df3cSHuacai Chen 	.action_msg     = "Show TLB entries",
58dea2df3cSHuacai Chen 	.enable_mask	= SYSRQ_ENABLE_DUMP,
59dea2df3cSHuacai Chen };
60dea2df3cSHuacai Chen 
loongarch_sysrq_init(void)61dea2df3cSHuacai Chen static int __init loongarch_sysrq_init(void)
62dea2df3cSHuacai Chen {
63dea2df3cSHuacai Chen 	return register_sysrq_key('x', &sysrq_tlbdump_op);
64dea2df3cSHuacai Chen }
65dea2df3cSHuacai Chen arch_initcall(loongarch_sysrq_init);
66