linux-parisc.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] Add KGDB support to parisc
@ 2019-04-02 20:48 Sven Schnelle
  2019-04-02 20:48 ` [PATCH 1/3] parisc: add set_fixmap()/clear_fixmap() Sven Schnelle
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Sven Schnelle @ 2019-04-02 20:48 UTC (permalink / raw)
  To: deller; +Cc: linux-parisc, Sven Schnelle

Hi,

these series add fixed mappings, a function to patch kernel text
with RO kernel text and kgdb support to parisc.

Fixed mappings are located at the end of the VMALLOC address range. patch_text()
is introduced based on the ARM implementation, which utilizies fixed mappings.
patch_text() only supports late patching, but we might extend it later with
early patching functionality. And last but not least the last patch adds KGDB
functionality. KGDB was tested on C3750 with a 32 and 64 bit kernel, on C8000
with 64 bit.

Sven Schnelle (3):
  parisc: add set_fixmap()/clear_fixmap()
  parisc: add parisc code patching
  parisc: add KGDB support

 arch/parisc/Kconfig              |   1 +
 arch/parisc/include/asm/fixmap.h |  19 ++-
 arch/parisc/include/asm/kgdb.h   |  68 ++++++++++
 arch/parisc/include/asm/patch.h  |   7 ++
 arch/parisc/kernel/Makefile      |   4 +-
 arch/parisc/kernel/kgdb.c        | 210 +++++++++++++++++++++++++++++++
 arch/parisc/kernel/patch.c       |  78 ++++++++++++
 arch/parisc/kernel/traps.c       |  15 +++
 arch/parisc/mm/Makefile          |   2 +-
 arch/parisc/mm/fixmap.c          |  43 +++++++
 arch/parisc/mm/init.c            |  14 ++-
 11 files changed, 453 insertions(+), 8 deletions(-)
 create mode 100644 arch/parisc/include/asm/kgdb.h
 create mode 100644 arch/parisc/include/asm/patch.h
 create mode 100644 arch/parisc/kernel/kgdb.c
 create mode 100644 arch/parisc/kernel/patch.c
 create mode 100644 arch/parisc/mm/fixmap.c

-- 
2.20.1


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 1/3] parisc: add set_fixmap()/clear_fixmap()
  2019-04-02 20:48 [PATCH 0/3] Add KGDB support to parisc Sven Schnelle
@ 2019-04-02 20:48 ` Sven Schnelle
  2019-04-02 20:48 ` [PATCH 2/3] parisc: add parisc code patching Sven Schnelle
  2019-04-02 20:48 ` [PATCH 3/3] parisc: add KGDB support Sven Schnelle
  2 siblings, 0 replies; 4+ messages in thread
From: Sven Schnelle @ 2019-04-02 20:48 UTC (permalink / raw)
  To: deller; +Cc: linux-parisc, Sven Schnelle

These functions will be used for adding code patching
functions later.

Signed-off-by: Sven Schnelle <svens@stackframe.org>
---
 arch/parisc/include/asm/fixmap.h | 19 +++++++++++++-
 arch/parisc/mm/Makefile          |  2 +-
 arch/parisc/mm/fixmap.c          | 43 ++++++++++++++++++++++++++++++++
 arch/parisc/mm/init.c            | 14 +++++++----
 4 files changed, 71 insertions(+), 7 deletions(-)
 create mode 100644 arch/parisc/mm/fixmap.c

diff --git a/arch/parisc/include/asm/fixmap.h b/arch/parisc/include/asm/fixmap.h
index f7c3a0905de4..288da73d4cc0 100644
--- a/arch/parisc/include/asm/fixmap.h
+++ b/arch/parisc/include/asm/fixmap.h
@@ -15,17 +15,34 @@
  * from areas congruently mapped with user space.  It is 8MB large
  * and must be 16MB aligned */
 #define TMPALIAS_MAP_START	((__PAGE_OFFSET) - 16*1024*1024)
+
+#define FIXMAP_SIZE		(FIX_BITMAP_COUNT << PAGE_SHIFT)
+#define FIXMAP_START		(TMPALIAS_MAP_START - FIXMAP_SIZE)
 /* This is the kernel area for all maps (vmalloc, dma etc.)  most
  * usually, it extends up to TMPALIAS_MAP_START.  Virtual addresses
  * 0..GATEWAY_PAGE_SIZE are reserved for the gateway page */
 #define KERNEL_MAP_START	(GATEWAY_PAGE_SIZE)
-#define KERNEL_MAP_END		(TMPALIAS_MAP_START)
+#define KERNEL_MAP_END		(FIXMAP_START)
 
 #ifndef __ASSEMBLY__
+
+
+enum fixed_addresses {
+	/* Support writing RO kernel text via kprobes, jump labels, etc. */
+	FIX_TEXT_POKE0,
+	FIX_BITMAP_COUNT
+};
+
 extern void *parisc_vmalloc_start;
 #define PCXL_DMA_MAP_SIZE	(8*1024*1024)
 #define VMALLOC_START		((unsigned long)parisc_vmalloc_start)
 #define VMALLOC_END		(KERNEL_MAP_END)
+
+#define __fix_to_virt(_x) (FIXMAP_START + ((_x) << PAGE_SHIFT))
+
+void set_fixmap(enum fixed_addresses idx, phys_addr_t phys);
+void clear_fixmap(enum fixed_addresses idx);
+
 #endif /*__ASSEMBLY__*/
 
 #endif /*_ASM_FIXMAP_H*/
diff --git a/arch/parisc/mm/Makefile b/arch/parisc/mm/Makefile
index 134393de69d2..20e39b043a60 100644
--- a/arch/parisc/mm/Makefile
+++ b/arch/parisc/mm/Makefile
@@ -2,5 +2,5 @@
 # Makefile for arch/parisc/mm
 #
 
-obj-y	 := init.o fault.o ioremap.o
+obj-y	 := init.o fault.o ioremap.o fixmap.o
 obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
diff --git a/arch/parisc/mm/fixmap.c b/arch/parisc/mm/fixmap.c
new file mode 100644
index 000000000000..6f9744c688ae
--- /dev/null
+++ b/arch/parisc/mm/fixmap.c
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * fixmaps for parisc
+ *
+ * Copyright (c) 2019 Sven Schnelle <svens@stackframe.org>
+ */
+
+#include <linux/kprobes.h>
+#include <linux/mm.h>
+#include <asm/cacheflush.h>
+#include <asm/fixmap.h>
+
+void set_fixmap(enum fixed_addresses idx, phys_addr_t phys)
+{
+	unsigned long vaddr = __fix_to_virt(idx);
+	pgd_t *pgd = pgd_offset_k(vaddr);
+	pmd_t *pmd = pmd_offset(pgd, vaddr);
+	pte_t *pte;
+
+	if (pmd_none(*pmd))
+		pmd = pmd_alloc(NULL, pgd, vaddr);
+
+	pte = pte_offset_kernel(pmd, vaddr);
+	if (pte_none(*pte))
+		pte = pte_alloc_kernel(pmd, vaddr);
+
+	set_pte_at(&init_mm, vaddr, pte, __mk_pte(phys, PAGE_KERNEL_RWX));
+	flush_tlb_kernel_range(vaddr, vaddr + PAGE_SIZE);
+}
+
+void clear_fixmap(enum fixed_addresses idx)
+{
+	unsigned long vaddr = __fix_to_virt(idx);
+	pgd_t *pgd = pgd_offset_k(vaddr);
+	pmd_t *pmd = pmd_offset(pgd, vaddr);
+	pte_t *pte = pte_offset_kernel(pmd, vaddr);
+
+	pte_clear(&init_mm, vaddr, pte);
+
+	flush_tlb_kernel_range(vaddr, vaddr + PAGE_SIZE);
+}
+
+
diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c
index d0b166256f1a..b2b52de2b82b 100644
--- a/arch/parisc/mm/init.c
+++ b/arch/parisc/mm/init.c
@@ -622,15 +622,19 @@ void __init mem_init(void)
 	 * But keep code for debugging purposes.
 	 */
 	printk("virtual kernel memory layout:\n"
-	       "    vmalloc : 0x%px - 0x%px   (%4ld MB)\n"
-	       "    memory  : 0x%px - 0x%px   (%4ld MB)\n"
-	       "      .init : 0x%px - 0x%px   (%4ld kB)\n"
-	       "      .data : 0x%px - 0x%px   (%4ld kB)\n"
-	       "      .text : 0x%px - 0x%px   (%4ld kB)\n",
+	       "     vmalloc : 0x%px - 0x%px   (%4ld MB)\n"
+	       "     fixmap  : 0x%px - 0x%px   (%4ld kB)\n"
+	       "     memory  : 0x%px - 0x%px   (%4ld MB)\n"
+	       "       .init : 0x%px - 0x%px   (%4ld kB)\n"
+	       "       .data : 0x%px - 0x%px   (%4ld kB)\n"
+	       "       .text : 0x%px - 0x%px   (%4ld kB)\n",
 
 	       (void*)VMALLOC_START, (void*)VMALLOC_END,
 	       (VMALLOC_END - VMALLOC_START) >> 20,
 
+	       (void *)FIXMAP_START, (void *)(FIXMAP_START + FIXMAP_SIZE),
+	       (unsigned long)(FIXMAP_SIZE / 1024),
+
 	       __va(0), high_memory,
 	       ((unsigned long)high_memory - (unsigned long)__va(0)) >> 20,
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 2/3] parisc: add parisc code patching
  2019-04-02 20:48 [PATCH 0/3] Add KGDB support to parisc Sven Schnelle
  2019-04-02 20:48 ` [PATCH 1/3] parisc: add set_fixmap()/clear_fixmap() Sven Schnelle
@ 2019-04-02 20:48 ` Sven Schnelle
  2019-04-02 20:48 ` [PATCH 3/3] parisc: add KGDB support Sven Schnelle
  2 siblings, 0 replies; 4+ messages in thread
From: Sven Schnelle @ 2019-04-02 20:48 UTC (permalink / raw)
  To: deller; +Cc: linux-parisc, Sven Schnelle

Instead of re-mapping the whole kernel text with RWX rights
add a patch_text() which can be used to replace instructions
in the kernel .text section. Based on the ARM implementation.

Signed-off-by: Sven Schnelle <svens@stackframe.org>
---
 arch/parisc/include/asm/patch.h |  7 +++
 arch/parisc/kernel/Makefile     |  3 +-
 arch/parisc/kernel/patch.c      | 78 +++++++++++++++++++++++++++++++++
 3 files changed, 87 insertions(+), 1 deletion(-)
 create mode 100644 arch/parisc/include/asm/patch.h
 create mode 100644 arch/parisc/kernel/patch.c

diff --git a/arch/parisc/include/asm/patch.h b/arch/parisc/include/asm/patch.h
new file mode 100644
index 000000000000..24ceb84519e4
--- /dev/null
+++ b/arch/parisc/include/asm/patch.h
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _PARISC_KERNEL_PATCH_H
+#define _PARISC_KERNEL_PATCH_H
+
+void patch_text(void *addr, unsigned int insn);
+
+#endif
diff --git a/arch/parisc/kernel/Makefile b/arch/parisc/kernel/Makefile
index 8e5f1ab65c68..d29bbd1a73b2 100644
--- a/arch/parisc/kernel/Makefile
+++ b/arch/parisc/kernel/Makefile
@@ -9,7 +9,8 @@ obj-y	     	:= cache.o pacache.o setup.o pdt.o traps.o time.o irq.o \
 		   pa7300lc.o syscall.o entry.o sys_parisc.o firmware.o \
 		   ptrace.o hardware.o inventory.o drivers.o alternative.o \
 		   signal.o hpmc.o real2.o parisc_ksyms.o unaligned.o \
-		   process.o processor.o pdc_cons.o pdc_chassis.o unwind.o
+		   process.o processor.o pdc_cons.o pdc_chassis.o unwind.o \
+		   patch.o
 
 ifdef CONFIG_FUNCTION_TRACER
 # Do not profile debug and lowlevel utilities
diff --git a/arch/parisc/kernel/patch.c b/arch/parisc/kernel/patch.c
new file mode 100644
index 000000000000..4a3bff87b177
--- /dev/null
+++ b/arch/parisc/kernel/patch.c
@@ -0,0 +1,78 @@
+// SPDX-License-Identifier: GPL-2.0
+ /*
+  * functions to patch RO kernel text during runtime
+  *
+  * Copyright (c) 2019 Sven Schnelle <svens@stackframe.org>
+  */
+
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/kprobes.h>
+#include <linux/mm.h>
+#include <linux/stop_machine.h>
+
+#include <asm/cacheflush.h>
+#include <asm/fixmap.h>
+#include <asm/patch.h>
+
+struct patch {
+	void *addr;
+	unsigned int insn;
+};
+
+static void __kprobes *patch_map(void *addr, int fixmap, unsigned long *flags)
+{
+	unsigned int uintaddr = (uintptr_t) addr;
+	bool module = !core_kernel_text(uintaddr);
+	struct page *page;
+
+	if (module && IS_ENABLED(CONFIG_STRICT_MODULE_RWX))
+		page = vmalloc_to_page(addr);
+	else if (!module && IS_ENABLED(CONFIG_STRICT_KERNEL_RWX))
+		page = virt_to_page(addr);
+	else
+		return addr;
+
+	set_fixmap(fixmap, page_to_phys(page));
+
+	return (void *) (__fix_to_virt(fixmap) + (uintaddr & ~PAGE_MASK));
+}
+
+static void __kprobes patch_unmap(int fixmap, unsigned long *flags)
+{
+	clear_fixmap(fixmap);
+}
+
+void __kprobes __patch_text(void *addr, unsigned int insn)
+{
+	unsigned long flags;
+	void *waddr = addr;
+	int size;
+
+	waddr = patch_map(addr, FIX_TEXT_POKE0, &flags);
+	*(u32 *)waddr = insn;
+	size = sizeof(u32);
+	flush_kernel_vmap_range(waddr, size);
+	patch_unmap(FIX_TEXT_POKE0, &flags);
+	flush_icache_range((uintptr_t)(addr),
+			   (uintptr_t)(addr) + size);
+}
+
+static int __kprobes patch_text_stop_machine(void *data)
+{
+	struct patch *patch = data;
+
+	__patch_text(patch->addr, patch->insn);
+
+	return 0;
+}
+
+void __kprobes patch_text(void *addr, unsigned int insn)
+{
+	struct patch patch = {
+		.addr = addr,
+		.insn = insn,
+	};
+
+	stop_machine_cpuslocked(patch_text_stop_machine, &patch, NULL);
+}
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 3/3] parisc: add KGDB support
  2019-04-02 20:48 [PATCH 0/3] Add KGDB support to parisc Sven Schnelle
  2019-04-02 20:48 ` [PATCH 1/3] parisc: add set_fixmap()/clear_fixmap() Sven Schnelle
  2019-04-02 20:48 ` [PATCH 2/3] parisc: add parisc code patching Sven Schnelle
@ 2019-04-02 20:48 ` Sven Schnelle
  2 siblings, 0 replies; 4+ messages in thread
From: Sven Schnelle @ 2019-04-02 20:48 UTC (permalink / raw)
  To: deller; +Cc: linux-parisc, Sven Schnelle

This patch add KGDB support to PA-RISC. It also implements
single-stepping utilizing the recovery counter.

Signed-off-by: Sven Schnelle <svens@stackframe.org>
---
 arch/parisc/Kconfig            |   1 +
 arch/parisc/include/asm/kgdb.h |  68 +++++++++++
 arch/parisc/kernel/Makefile    |   1 +
 arch/parisc/kernel/kgdb.c      | 210 +++++++++++++++++++++++++++++++++
 arch/parisc/kernel/traps.c     |  15 +++
 5 files changed, 295 insertions(+)
 create mode 100644 arch/parisc/include/asm/kgdb.h
 create mode 100644 arch/parisc/kernel/kgdb.c

diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index c8e621296092..a80c19c7fc0e 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -54,6 +54,7 @@ config PARISC
 	select CPU_NO_EFFICIENT_FFS
 	select NEED_DMA_MAP_STATE
 	select NEED_SG_DMA_LENGTH
+	select HAVE_ARCH_KGDB
 
 	help
 	  The PA-RISC microprocessor is designed by Hewlett-Packard and used
diff --git a/arch/parisc/include/asm/kgdb.h b/arch/parisc/include/asm/kgdb.h
new file mode 100644
index 000000000000..f23e7f8f13a5
--- /dev/null
+++ b/arch/parisc/include/asm/kgdb.h
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * PA-RISC KGDB support
+ *
+ * Copyright (c) 2019 Sven Schnelle <svens@stackframe.org>
+ *
+ */
+
+#ifndef __PARISC_KGDB_H__
+#define __PARISC_KGDB_H__
+
+#define BREAK_INSTR_SIZE		4
+#define PARISC_KGDB_COMPILED_BREAK_INSN	0x3ffc01f
+#define PARISC_KGDB_BREAK_INSN		0x3ffa01f
+
+
+#define NUMREGBYTES			sizeof(struct parisc_gdb_regs)
+#define BUFMAX				4096
+
+#define CACHE_FLUSH_IS_SAFE		1
+
+#ifndef __ASSEMBLY__
+
+static inline void arch_kgdb_breakpoint(void)
+{
+	asm(".word %0" : : "i"(PARISC_KGDB_COMPILED_BREAK_INSN) : "memory");
+}
+
+struct parisc_gdb_regs {
+	unsigned long gpr[32];
+	unsigned long sar;
+	unsigned long iaoq_f;
+	unsigned long iasq_f;
+	unsigned long iaoq_b;
+	unsigned long iasq_b;
+	unsigned long eiem;
+	unsigned long iir;
+	unsigned long isr;
+	unsigned long ior;
+	unsigned long ipsw;
+	unsigned long __unused0;
+	unsigned long sr4;
+	unsigned long sr0;
+	unsigned long sr1;
+	unsigned long sr2;
+	unsigned long sr3;
+	unsigned long sr5;
+	unsigned long sr6;
+	unsigned long sr7;
+	unsigned long cr0;
+	unsigned long pid1;
+	unsigned long pid2;
+	unsigned long scrccr;
+	unsigned long pid3;
+	unsigned long pid4;
+	unsigned long cr24;
+	unsigned long cr25;
+	unsigned long cr26;
+	unsigned long cr27;
+	unsigned long cr28;
+	unsigned long cr29;
+	unsigned long cr30;
+
+	u64 fr[32];
+};
+
+#endif
+#endif
diff --git a/arch/parisc/kernel/Makefile b/arch/parisc/kernel/Makefile
index d29bbd1a73b2..5012da96c196 100644
--- a/arch/parisc/kernel/Makefile
+++ b/arch/parisc/kernel/Makefile
@@ -33,3 +33,4 @@ obj-$(CONFIG_64BIT)	+= perf.o perf_asm.o $(obj64-y)
 obj-$(CONFIG_PARISC_CPU_TOPOLOGY)	+= topology.o
 obj-$(CONFIG_FUNCTION_TRACER)		+= ftrace.o
 obj-$(CONFIG_FUNCTION_GRAPH_TRACER)	+= ftrace.o
+obj-$(CONFIG_KGDB)			+= kgdb.o
diff --git a/arch/parisc/kernel/kgdb.c b/arch/parisc/kernel/kgdb.c
new file mode 100644
index 000000000000..9836e06d20ab
--- /dev/null
+++ b/arch/parisc/kernel/kgdb.c
@@ -0,0 +1,210 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PA-RISC KGDB support
+ *
+ * Copyright (c) 2019 Sven Schnelle <svens@stackframe.org>
+ *
+ */
+
+#include <linux/kgdb.h>
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/notifier.h>
+#include <linux/kdebug.h>
+#include <linux/uaccess.h>
+#include <asm/ptrace.h>
+#include <asm/traps.h>
+#include <asm/processor.h>
+#include <asm/patch.h>
+#include <asm/cacheflush.h>
+
+const struct kgdb_arch arch_kgdb_ops = {
+	.gdb_bpt_instr = { 0x03, 0xff, 0xa0, 0x1f }
+};
+
+static int __kgdb_notify(struct die_args *args, unsigned long cmd)
+{
+	struct pt_regs *regs = args->regs;
+
+	if (kgdb_handle_exception(1, args->signr, cmd, regs))
+		return NOTIFY_DONE;
+	return NOTIFY_STOP;
+}
+
+static int kgdb_notify(struct notifier_block *self,
+		       unsigned long cmd, void *ptr)
+{
+	unsigned long flags;
+	int ret;
+
+	local_irq_save(flags);
+	ret = __kgdb_notify(ptr, cmd);
+	local_irq_restore(flags);
+
+	return ret;
+}
+
+static struct notifier_block kgdb_notifier = {
+	.notifier_call	= kgdb_notify,
+	.priority	= -INT_MAX,
+};
+
+int kgdb_arch_init(void)
+{
+	return register_die_notifier(&kgdb_notifier);
+}
+
+void kgdb_arch_exit(void)
+{
+	unregister_die_notifier(&kgdb_notifier);
+}
+
+void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
+{
+	struct parisc_gdb_regs *gr = (struct parisc_gdb_regs *)gdb_regs;
+
+	memset(gr, 0, sizeof(struct parisc_gdb_regs));
+
+	memcpy(gr->gpr, regs->gr, sizeof(gr->gpr));
+	memcpy(gr->fr, regs->fr, sizeof(gr->fr));
+
+	gr->sr0 = regs->sr[0];
+	gr->sr1 = regs->sr[1];
+	gr->sr2 = regs->sr[2];
+	gr->sr3 = regs->sr[3];
+	gr->sr4 = regs->sr[4];
+	gr->sr5 = regs->sr[5];
+	gr->sr6 = regs->sr[6];
+	gr->sr7 = regs->sr[7];
+
+	gr->sar = regs->sar;
+	gr->iir = regs->iir;
+	gr->isr = regs->isr;
+	gr->ior = regs->ior;
+	gr->ipsw = regs->ipsw;
+	gr->cr27 = regs->cr27;
+
+	gr->iaoq_f = regs->iaoq[0];
+	gr->iasq_f = regs->iasq[0];
+
+	gr->iaoq_b = regs->iaoq[1];
+	gr->iasq_b = regs->iasq[1];
+}
+
+void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
+{
+	struct parisc_gdb_regs *gr = (struct parisc_gdb_regs *)gdb_regs;
+
+
+	memcpy(regs->gr, gr->gpr, sizeof(regs->gr));
+	memcpy(regs->fr, gr->fr, sizeof(regs->fr));
+
+	regs->sr[0] = gr->sr0;
+	regs->sr[1] = gr->sr1;
+	regs->sr[2] = gr->sr2;
+	regs->sr[3] = gr->sr3;
+	regs->sr[4] = gr->sr4;
+	regs->sr[5] = gr->sr5;
+	regs->sr[6] = gr->sr6;
+	regs->sr[7] = gr->sr7;
+
+	regs->sar = gr->sar;
+	regs->iir = gr->iir;
+	regs->isr = gr->isr;
+	regs->ior = gr->ior;
+	regs->ipsw = gr->ipsw;
+	regs->cr27 = gr->cr27;
+
+	regs->iaoq[0] = gr->iaoq_f;
+	regs->iasq[0] = gr->iasq_f;
+
+	regs->iaoq[1] = gr->iaoq_b;
+	regs->iasq[1] = gr->iasq_b;
+}
+
+void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs,
+				struct task_struct *task)
+{
+	struct pt_regs *regs = task_pt_regs(task);
+	unsigned long gr30, iaoq;
+
+	gr30 = regs->gr[30];
+	iaoq = regs->iaoq[0];
+
+	regs->gr[30] = regs->ksp;
+	regs->iaoq[0] = regs->kpc;
+	pt_regs_to_gdb_regs(gdb_regs, regs);
+
+	regs->gr[30] = gr30;
+	regs->iaoq[0] = iaoq;
+
+}
+
+static void step_instruction_queue(struct pt_regs *regs)
+{
+	regs->iaoq[0] = regs->iaoq[1];
+	regs->iaoq[1] += 4;
+}
+
+void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long ip)
+{
+	regs->iaoq[0] = ip;
+	regs->iaoq[1] = ip + 4;
+}
+
+int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt)
+{
+	int ret = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr,
+				BREAK_INSTR_SIZE);
+	if (ret)
+		return ret;
+
+	patch_text((void *)bpt->bpt_addr,
+			*(unsigned int *)&arch_kgdb_ops.gdb_bpt_instr);
+	return ret;
+}
+
+int kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt)
+{
+	patch_text((void *)bpt->bpt_addr, *(unsigned int *)&bpt->saved_instr);
+	return 0;
+}
+
+int kgdb_arch_handle_exception(int trap, int signo,
+		int err_code, char *inbuf, char *outbuf,
+		struct pt_regs *regs)
+{
+	unsigned long addr;
+	char *p = inbuf + 1;
+
+	switch (inbuf[0]) {
+	case 'D':
+	case 'c':
+	case 'k':
+		kgdb_contthread = NULL;
+		kgdb_single_step = 0;
+
+		if (kgdb_hex2long(&p, &addr))
+			kgdb_arch_set_pc(regs, addr);
+		else if (trap == 9 && regs->iir ==
+				PARISC_KGDB_COMPILED_BREAK_INSN)
+			step_instruction_queue(regs);
+		return 0;
+	case 's':
+		kgdb_single_step = 1;
+		if (kgdb_hex2long(&p, &addr)) {
+			kgdb_arch_set_pc(regs, addr);
+		} else if (trap == 9 && regs->iir ==
+				PARISC_KGDB_COMPILED_BREAK_INSN) {
+			step_instruction_queue(regs);
+			mtctl(-1, 0);
+		} else {
+			mtctl(0, 0);
+		}
+		regs->gr[0] |= PSW_R;
+		return 0;
+
+	}
+	return -1;
+}
+
diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c
index 7e1ccafadf57..91f94fc2abd3 100644
--- a/arch/parisc/kernel/traps.c
+++ b/arch/parisc/kernel/traps.c
@@ -42,6 +42,7 @@
 #include <asm/unwind.h>
 #include <asm/tlbflush.h>
 #include <asm/cacheflush.h>
+#include <linux/kgdb.h>
 
 #include "../math-emu/math-emu.h"	/* for handle_fpe() */
 
@@ -293,6 +294,14 @@ static void handle_break(struct pt_regs *regs)
 			(tt == BUG_TRAP_TYPE_NONE) ? 9 : 0);
 	}
 
+#ifdef CONFIG_KGDB
+	if (unlikely(iir == PARISC_KGDB_COMPILED_BREAK_INSN ||
+		iir == PARISC_KGDB_BREAK_INSN)) {
+		kgdb_handle_exception(9, SIGTRAP, 0, regs);
+		return;
+	}
+#endif
+
 	if (unlikely(iir != GDB_BREAK_INSN))
 		parisc_printk_ratelimited(0, regs,
 			KERN_DEBUG "break %d,%d: pid=%d command='%s'\n",
@@ -518,6 +527,12 @@ void notrace handle_interruption(int code, struct pt_regs *regs)
 	case  3:
 		/* Recovery counter trap */
 		regs->gr[0] &= ~PSW_R;
+
+		if (kgdb_single_step) {
+			kgdb_handle_exception(0, SIGTRAP, 0, regs);
+			return;
+		}
+
 		if (user_space(regs))
 			handle_gdb_break(regs, TRAP_TRACE);
 		/* else this must be the start of a syscall - just let it run */
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2019-04-02 20:48 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-04-02 20:48 [PATCH 0/3] Add KGDB support to parisc Sven Schnelle
2019-04-02 20:48 ` [PATCH 1/3] parisc: add set_fixmap()/clear_fixmap() Sven Schnelle
2019-04-02 20:48 ` [PATCH 2/3] parisc: add parisc code patching Sven Schnelle
2019-04-02 20:48 ` [PATCH 3/3] parisc: add KGDB support Sven Schnelle

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).