Module Name: src
Committed By: thorpej
Date: Sun Mar 16 22:34:36 UTC 2025
Modified Files:
src/sys/arch/alpha/alpha: fp_complete.c
Log Message:
Convert the 24 year-old "temporary trap shadow instrumentation" to use
event counters (so they're generally visible) and atomics to adjust them
(so they're not total jibberish on MP systems).
To generate a diff of this commit:
cvs rdiff -u -r1.32 -r1.33 src/sys/arch/alpha/alpha/fp_complete.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/arch/alpha/alpha/fp_complete.c
diff -u src/sys/arch/alpha/alpha/fp_complete.c:1.32 src/sys/arch/alpha/alpha/fp_complete.c:1.33
--- src/sys/arch/alpha/alpha/fp_complete.c:1.32 Sun Mar 16 19:27:30 2025
+++ src/sys/arch/alpha/alpha/fp_complete.c Sun Mar 16 22:34:36 2025
@@ -1,4 +1,4 @@
-/* $NetBSD: fp_complete.c,v 1.32 2025/03/16 19:27:30 thorpej Exp $ */
+/* $NetBSD: fp_complete.c,v 1.33 2025/03/16 22:34:36 thorpej Exp $ */
/*-
* Copyright (c) 2001 Ross Harvey
@@ -37,7 +37,7 @@
#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
-__KERNEL_RCSID(0, "$NetBSD: fp_complete.c,v 1.32 2025/03/16 19:27:30 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fp_complete.c,v 1.33 2025/03/16 22:34:36 thorpej Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -130,21 +130,22 @@ static struct evcnt fpevent_reuse;
* user code has met AARM trap shadow generation requirements.
*/
+static struct evcnt ts_scans; /* trap shadow scans */
+static struct evcnt ts_insns; /* total scanned insns */
+static struct evcnt ts_insns_max; /* per-scan high water mark */
+static struct evcnt ts_resolved; /* cases trigger pc found */
+static struct evcnt ts_unresolved; /* cases it wasn't, code problems? */
+
+static struct evcnt fp_ill_opc; /* unexpected op codes */
+static struct evcnt fp_ill_func; /* unexpected function codes */
+static struct evcnt fp_ill_anyop; /* this "cannot happen" */
+
+static struct evcnt fp_vax; /* traps from VAX FP insns */
+
struct alpha_shadow {
- uint64_t resolved; /* cases trigger pc found */
- uint64_t unresolved; /* cases it wasn't, code problems? */
- uint64_t scans; /* trap shadow scans */
- uint64_t len; /* number of instructions examined */
uint64_t uop; /* bit mask of unexpected opcodes */
- uint64_t sqrts; /* ev6+ square root single count */
- uint64_t sqrtt; /* ev6+ square root double count */
- uint32_t ufunc; /* bit mask of unexpected functions */
- uint32_t max; /* max trap shadow scan */
- uint32_t nilswop; /* unexpected op codes */
- uint32_t nilswfunc; /* unexpected function codes */
- uint32_t nilanyop; /* this "cannot happen" */
- uint32_t vax; /* sigs from vax fp opcodes */
-} alpha_shadow, alpha_shadow_zero;
+ uint32_t ufunc; /* bit mask of unexpected functions */
+} alpha_shadow;
static float64 float64_unk(float64, float64);
static float64 compare_un(float64, float64);
@@ -178,7 +179,7 @@ this_cannot_happen(int what_cannot_happe
static uint64_t reported;
inst.bits = bits;
- ++alpha_shadow.nilswfunc;
+ atomic_inc_ulong(&fp_ill_func.ev_count);
if (bits != -1)
alpha_shadow.uop |= 1UL << inst.generic_format.opcode;
if (1UL << what_cannot_happen & reported)
@@ -567,6 +568,7 @@ alpha_fp_interpret(unsigned long pc, str
switch(inst.generic_format.opcode) {
default:
/* this "cannot happen" */
+ atomic_inc_ulong(&fp_ill_opc.ev_count);
this_cannot_happen(2, inst.bits);
return;
case op_any_float:
@@ -577,12 +579,13 @@ alpha_fp_interpret(unsigned long pc, str
alpha_lds(inst.float_detail.fc, &sfc);
float_raise(FP_X_INV);
} else {
- ++alpha_shadow.nilanyop;
+ atomic_inc_ulong(&fp_ill_anyop.ev_count);
this_cannot_happen(3, inst.bits);
}
break;
case op_vax_float:
- ++alpha_shadow.vax; /* fall thru */
+ atomic_inc_ulong(&fp_vax.ev_count);
+ /* FALLTHROUGH */ /* XXX */
case op_ieee_float:
case op_fix_float:
switch(inst.float_detail.src) {
@@ -682,13 +685,13 @@ alpha_fp_complete_at(unsigned long trigg
int
alpha_fp_complete(u_long a0, u_long a1, struct lwp *l, uint64_t *ucode)
{
- int t;
- int sig;
uint64_t op_class;
alpha_instruction inst;
/* "trigger_pc" is Compaq's term for the earliest faulting op */
alpha_instruction *trigger_pc, *usertrap_pc;
alpha_instruction *pc, *win_begin, tsw[TSWINSIZE];
+ long insn_count = 0;
+ int sig;
if (alpha_fp_complete_debug) {
printf("%s: [%s:%d] a0[AESR]=0x%lx a1[regmask]=0x%lx "
@@ -731,10 +734,9 @@ alpha_fp_complete(u_long a0, u_long a1,
*/
trigger_pc = 0;
win_begin = pc;
- ++alpha_shadow.scans;
- t = alpha_shadow.len;
+ atomic_inc_ulong(&ts_scans.ev_count);
for (--pc; a1; --pc) {
- ++alpha_shadow.len;
+ insn_count++;
if (pc < win_begin) {
win_begin = pc - TSWINSIZE + 1;
if (copyin(win_begin, tsw, sizeof tsw)) {
@@ -768,15 +770,16 @@ alpha_fp_complete(u_long a0, u_long a1,
}
/* Some shadow-safe op, probably load, store, or FPTI class */
}
- t = alpha_shadow.len - t;
- if (t > alpha_shadow.max)
- alpha_shadow.max = t;
+ if (insn_count > atomic_load_relaxed(&ts_insns_max.ev_count)) {
+ atomic_store_relaxed(&ts_insns_max.ev_count, insn_count);
+ }
+ atomic_add_long(&ts_insns.ev_count, insn_count);
if (__predict_true(trigger_pc != 0 && a1 == 0)) {
- ++alpha_shadow.resolved;
+ atomic_inc_ulong(&ts_resolved.ev_count);
sig = alpha_fp_complete_at((u_long)trigger_pc, l, ucode);
goto resolved;
} else {
- ++alpha_shadow.unresolved;
+ atomic_inc_ulong(&ts_unresolved.ev_count);
}
unresolved: /* obligatory statement */;
@@ -828,6 +831,24 @@ alpha_fp_init(void)
"FP", "proc use");
evcnt_attach_dynamic_nozero(&fpevent_reuse, EVCNT_TYPE_MISC, NULL,
"FP", "proc re-use");
+
+ evcnt_attach_dynamic_nozero(&ts_scans, EVCNT_TYPE_MISC, NULL,
+ "FP", "TS scans");
+ evcnt_attach_dynamic_nozero(&ts_insns, EVCNT_TYPE_MISC, NULL,
+ "FP", "TS total insns");
+ evcnt_attach_dynamic_nozero(&ts_insns_max, EVCNT_TYPE_MISC, NULL,
+ "FP", "TS max single-scan insns");
+ evcnt_attach_dynamic_nozero(&ts_resolved, EVCNT_TYPE_MISC, NULL,
+ "FP", "TS resolved");
+ evcnt_attach_dynamic_nozero(&ts_unresolved, EVCNT_TYPE_MISC, NULL,
+ "FP", "TS unresolved");
+
+ evcnt_attach_dynamic_nozero(&fp_ill_opc, EVCNT_TYPE_MISC, NULL,
+ "FP", "illegal op code");
+ evcnt_attach_dynamic_nozero(&fp_ill_func, EVCNT_TYPE_MISC, NULL,
+ "FP", "illegal function code");
+ evcnt_attach_dynamic_nozero(&fp_ill_anyop, EVCNT_TYPE_MISC, NULL,
+ "FP", "illegal any_float function code");
}
/*