[RFC PATCH 13/13] ARC: pt_regs: handle the case when ZOL is not supported

Sergey Matyukevich geomatsi at gmail.com
Tue Feb 22 06:15:06 PST 2022


From: Vineet Gupta <vgupta at kernel.org>

- Entry code (interrupts/exceptions) need not save/restore ZOL regs
- Any userspace ZOL references (ptrace, signal frame, process start)
  reworked such that ZOL regs are Zero-on-read, Ingore-on-write since
  the ptrace ABI need not change

Signed-off-by: Vineet Gupta <vgupta at kernel.org>
---
 arch/arc/include/asm/entry-arcv2.h |  4 ++++
 arch/arc/include/asm/ptrace.h      |  4 +++-
 arch/arc/kernel/asm-offsets.c      |  2 ++
 arch/arc/kernel/disasm.c           |  2 ++
 arch/arc/kernel/intc-arcv2.c       |  2 ++
 arch/arc/kernel/kgdb.c             |  4 ++++
 arch/arc/kernel/process.c          |  2 ++
 arch/arc/kernel/ptrace.c           | 12 ++++++++++++
 arch/arc/kernel/signal.c           |  8 ++++++++
 arch/arc/kernel/troubleshoot.c     |  3 +++
 arch/arc/kernel/unaligned.c        |  2 ++
 11 files changed, 44 insertions(+), 1 deletion(-)

diff --git a/arch/arc/include/asm/entry-arcv2.h b/arch/arc/include/asm/entry-arcv2.h
index 0ff4c0610561..e40a98d2ec29 100644
--- a/arch/arc/include/asm/entry-arcv2.h
+++ b/arch/arc/include/asm/entry-arcv2.h
@@ -117,11 +117,13 @@
 
 	st	blink, [sp, PT_blink]
 
+#ifndef CONFIG_ARC_LACKS_ZOL
 	lr	r10, [lp_end]
 	lr	r11, [lp_start]
 	ST2	r10, r11, PT_lpe
 
 	st	lp_count, [sp, PT_lpc]
+#endif
 
 	; skip JLI, LDI, EI for now
 .endm
@@ -205,12 +207,14 @@
 
 	ld	blink, [sp, PT_blink]
 
+#ifndef CONFIG_ARC_LACKS_ZOL
 	LD2	r10, r11, PT_lpe
 	sr	r10, [lp_end]
 	sr	r11, [lp_start]
 
 	ld	r10, [sp, PT_lpc]	; lp_count can't be target of LD
 	mov	lp_count, r10
+#endif
 
 	LD2	r0,  r1,  PT_r0
 	LD2	r2,  r3,  PT_r2
diff --git a/arch/arc/include/asm/ptrace.h b/arch/arc/include/asm/ptrace.h
index cca8d6583e31..9d2b1e7ba6a3 100644
--- a/arch/arc/include/asm/ptrace.h
+++ b/arch/arc/include/asm/ptrace.h
@@ -94,8 +94,10 @@ struct pt_regs {
 	unsigned long r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11;
 
 	unsigned long blink;
-	unsigned long lp_end, lp_start, lp_count;
 
+#ifndef CONFIG_ARC_LACKS_ZOL
+	unsigned long lp_end, lp_start, lp_count;
+#endif
 	unsigned long ei, ldi, jli;
 
 	unsigned long ret;
diff --git a/arch/arc/kernel/asm-offsets.c b/arch/arc/kernel/asm-offsets.c
index 0e884036ab74..e388d3420b3d 100644
--- a/arch/arc/kernel/asm-offsets.c
+++ b/arch/arc/kernel/asm-offsets.c
@@ -61,8 +61,10 @@ int main(void)
 	DEFINE(PT_r26, offsetof(struct pt_regs, r26));
 	DEFINE(PT_ret, offsetof(struct pt_regs, ret));
 	DEFINE(PT_blink, offsetof(struct pt_regs, blink));
+#ifndef CONFIG_ARC_LACKS_ZOL
 	DEFINE(PT_lpe, offsetof(struct pt_regs, lp_end));
 	DEFINE(PT_lpc, offsetof(struct pt_regs, lp_count));
+#endif
 	DEFINE(PT_user_r25, offsetof(struct pt_regs, user_r25));
 
 	DEFINE(SZ_CALLEE_REGS, sizeof(struct callee_regs));
diff --git a/arch/arc/kernel/disasm.c b/arch/arc/kernel/disasm.c
index 03f8b1be0c3a..c23d3829aef6 100644
--- a/arch/arc/kernel/disasm.c
+++ b/arch/arc/kernel/disasm.c
@@ -523,11 +523,13 @@ int __kprobes disasm_next_pc(unsigned long pc, struct pt_regs *regs,
 		*next_pc += instr_d.instr_len;
 	 }
 
+#ifndef CONFIG_ARC_LACKS_ZOL
 	 /* Zero Overhead Loop - end of the loop */
 	if (!(regs->status32 & STATUS32_L) && (*next_pc == regs->lp_end)
 		&& (regs->lp_count > 1)) {
 		*next_pc = regs->lp_start;
 	}
+#endif
 
 	return instr.is_branch;
 }
diff --git a/arch/arc/kernel/intc-arcv2.c b/arch/arc/kernel/intc-arcv2.c
index 5cda19d0aa91..7c1d8b2c4dce 100644
--- a/arch/arc/kernel/intc-arcv2.c
+++ b/arch/arc/kernel/intc-arcv2.c
@@ -48,7 +48,9 @@ void arc_init_IRQ(void)
 #ifndef CONFIG_ARC_IRQ_NO_AUTOSAVE
 	ictrl.save_nr_gpr_pairs = 6;	/* r0 to r11 (r12 saved manually) */
 	ictrl.save_blink = 1;
+#ifndef CONFIG_ARC_LACKS_ZOL
 	ictrl.save_lp_regs = 1;		/* LP_COUNT, LP_START, LP_END */
+#endif
 	ictrl.save_u_to_u = 0;		/* user ctxt saved on kernel stack */
 	ictrl.save_idx_regs = 1;	/* JLI, LDI, EI */
 #endif
diff --git a/arch/arc/kernel/kgdb.c b/arch/arc/kernel/kgdb.c
index 345a0000554c..6f237fdc6e54 100644
--- a/arch/arc/kernel/kgdb.c
+++ b/arch/arc/kernel/kgdb.c
@@ -27,9 +27,11 @@ static void to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *kernel_regs,
 	gdb_regs[_BLINK]	= kernel_regs->blink;
 	gdb_regs[_RET]		= kernel_regs->ret;
 	gdb_regs[_STATUS32]	= kernel_regs->status32;
+#ifndef CONFIG_ARC_LACKS_ZOL
 	gdb_regs[_LP_COUNT]	= kernel_regs->lp_count;
 	gdb_regs[_LP_END]	= kernel_regs->lp_end;
 	gdb_regs[_LP_START]	= kernel_regs->lp_start;
+#endif
 	gdb_regs[_BTA]		= kernel_regs->bta;
 	gdb_regs[_STOP_PC]	= kernel_regs->ret;
 }
@@ -47,9 +49,11 @@ static void from_gdb_regs(unsigned long *gdb_regs, struct pt_regs *kernel_regs,
 	kernel_regs->blink	= gdb_regs[_BLINK];
 	kernel_regs->ret	= gdb_regs[_RET];
 	kernel_regs->status32	= gdb_regs[_STATUS32];
+#ifndef CONFIG_ARC_LACKS_ZOL
 	kernel_regs->lp_count	= gdb_regs[_LP_COUNT];
 	kernel_regs->lp_end	= gdb_regs[_LP_END];
 	kernel_regs->lp_start	= gdb_regs[_LP_START];
+#endif
 	kernel_regs->bta	= gdb_regs[_BTA];
 }
 
diff --git a/arch/arc/kernel/process.c b/arch/arc/kernel/process.c
index 8e90052f6f05..2de60b74d462 100644
--- a/arch/arc/kernel/process.c
+++ b/arch/arc/kernel/process.c
@@ -269,9 +269,11 @@ void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long usp)
 
 	fpu_init_task(regs);
 
+#ifndef CONFIG_ARC_LACKS_ZOL
 	/* bogus seed values for debugging */
 	regs->lp_start = 0x10;
 	regs->lp_end = 0x80;
+#endif
 }
 
 /*
diff --git a/arch/arc/kernel/ptrace.c b/arch/arc/kernel/ptrace.c
index 883391977fdf..d3b98c9749e4 100644
--- a/arch/arc/kernel/ptrace.c
+++ b/arch/arc/kernel/ptrace.c
@@ -26,9 +26,15 @@ static int genregs_get(struct task_struct *target,
 
 	membuf_zero(&to, 4);	// pad
 	membuf_store(&to, ptregs->bta);
+#ifndef CONFIG_ARC_LACKS_ZOL
 	membuf_store(&to, ptregs->lp_start);
 	membuf_store(&to, ptregs->lp_end);
 	membuf_store(&to, ptregs->lp_count);
+#else
+	membuf_zero(&to, 4);	// ptregs->lp_start
+	membuf_zero(&to, 4);	// ptregs->lp_end
+	membuf_zero(&to, 4);	// ptregs->lp_count
+#endif
 	membuf_store(&to, ptregs->status32);
 	membuf_store(&to, ptregs->ret);
 	membuf_store(&to, ptregs->blink);
@@ -107,9 +113,15 @@ static int genregs_set(struct task_struct *target,
 	REG_IGNORE_ONE(pad);
 
 	REG_IN_ONE(scratch.bta, &ptregs->bta);
+#ifndef CONFIG_ARC_LACKS_ZOL
 	REG_IN_ONE(scratch.lp_start, &ptregs->lp_start);
 	REG_IN_ONE(scratch.lp_end, &ptregs->lp_end);
 	REG_IN_ONE(scratch.lp_count, &ptregs->lp_count);
+#else
+	REG_IGNORE_ONE(scratch.lp_start);
+	REG_IGNORE_ONE(scratch.lp_end);
+	REG_IGNORE_ONE(scratch.lp_count);
+#endif
 
 	REG_IGNORE_ONE(scratch.status32);
 
diff --git a/arch/arc/kernel/signal.c b/arch/arc/kernel/signal.c
index cb2f88502baf..449a4b0c6453 100644
--- a/arch/arc/kernel/signal.c
+++ b/arch/arc/kernel/signal.c
@@ -104,9 +104,15 @@ stash_usr_regs(struct rt_sigframe __user *sf, struct pt_regs *regs,
 	struct user_regs_struct uregs;
 
 	uregs.scratch.bta	= regs->bta;
+#ifndef CONFIG_ARC_LACKS_ZOL
 	uregs.scratch.lp_start	= regs->lp_start;
 	uregs.scratch.lp_end	= regs->lp_end;
 	uregs.scratch.lp_count	= regs->lp_count;
+#else
+	uregs.scratch.lp_start	= 0;
+	uregs.scratch.lp_end	= 0;
+	uregs.scratch.lp_count	= 0;
+#endif
 	uregs.scratch.status32	= regs->status32;
 	uregs.scratch.ret	= regs->ret;
 	uregs.scratch.blink	= regs->blink;
@@ -157,9 +163,11 @@ static int restore_usr_regs(struct pt_regs *regs, struct rt_sigframe __user *sf)
 
 	set_current_blocked(&set);
 	regs->bta	= uregs.scratch.bta;
+#ifndef CONFIG_ARC_LACKS_ZOL
 	regs->lp_start	= uregs.scratch.lp_start;
 	regs->lp_end	= uregs.scratch.lp_end;
 	regs->lp_count	= uregs.scratch.lp_count;
+#endif
 	regs->status32	= uregs.scratch.status32;
 	regs->ret	= uregs.scratch.ret;
 	regs->blink	= uregs.scratch.blink;
diff --git a/arch/arc/kernel/troubleshoot.c b/arch/arc/kernel/troubleshoot.c
index 7654c2e42dc0..acb7ee6c024d 100644
--- a/arch/arc/kernel/troubleshoot.c
+++ b/arch/arc/kernel/troubleshoot.c
@@ -22,8 +22,11 @@ static noinline void print_regs_scratch(struct pt_regs *regs)
 {
 	pr_cont("BTA: 0x%08lx\n SP: 0x%08lx  FP: 0x%08lx BLK: %pS\n",
 		regs->bta, regs->sp, regs->fp, (void *)regs->blink);
+
+#ifndef CONFIG_ARC_LACKS_ZOL
 	pr_cont("LPS: 0x%08lx\tLPE: 0x%08lx\tLPC: 0x%08lx\n",
 		regs->lp_start, regs->lp_end, regs->lp_count);
+#endif
 
 	pr_info("r00: 0x%08lx\tr01: 0x%08lx\tr02: 0x%08lx\n"	\
 		"r03: 0x%08lx\tr04: 0x%08lx\tr05: 0x%08lx\n"	\
diff --git a/arch/arc/kernel/unaligned.c b/arch/arc/kernel/unaligned.c
index d63ebd81f1c6..0937441bce04 100644
--- a/arch/arc/kernel/unaligned.c
+++ b/arch/arc/kernel/unaligned.c
@@ -244,11 +244,13 @@ int misaligned_fixup(unsigned long address, struct pt_regs *regs,
 	} else {
 		regs->ret += state.instr_len;
 
+#ifndef CONFIG_ARC_LACKS_ZOL
 		/* handle zero-overhead-loop */
 		if ((regs->ret == regs->lp_end) && (regs->lp_count)) {
 			regs->ret = regs->lp_start;
 			regs->lp_count--;
 		}
+#endif
 	}
 
 	perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, regs, address);
-- 
2.25.1




More information about the linux-snps-arc mailing list