[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