Module Name: src
Committed By: thorpej
Date: Mon Jul 19 22:21:36 UTC 2021
Modified Files:
src/sys/arch/alpha/alpha: trap.c
Log Message:
- In unaligned_fixup(), use defined constants for opcodes, not magic numbers.
- In handle_opdec(), use ufetch_int() to fetch the instruction and
_u{fetch,store}_{8,16}() when emulating BWX instructions rather
than copyin() / copyout() (they're faster).
- Add event counters for BWX instruction emulation.
To generate a diff of this commit:
cvs rdiff -u -r1.135 -r1.136 src/sys/arch/alpha/alpha/trap.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/trap.c
diff -u src/sys/arch/alpha/alpha/trap.c:1.135 src/sys/arch/alpha/alpha/trap.c:1.136
--- src/sys/arch/alpha/alpha/trap.c:1.135 Thu Nov 21 19:23:58 2019
+++ src/sys/arch/alpha/alpha/trap.c Mon Jul 19 22:21:36 2021
@@ -1,4 +1,4 @@
-/* $NetBSD: trap.c,v 1.135 2019/11/21 19:23:58 ad Exp $ */
+/* $NetBSD: trap.c,v 1.136 2021/07/19 22:21:36 thorpej Exp $ */
/*-
* Copyright (c) 2000, 2001 The NetBSD Foundation, Inc.
@@ -87,13 +87,15 @@
* rights to redistribute these changes.
*/
+#define __UFETCHSTORE_PRIVATE /* see handle_opdec() */
+
#include "opt_fix_unaligned_vax_fp.h"
#include "opt_ddb.h"
#include "opt_multiprocessor.h"
#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
-__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.135 2019/11/21 19:23:58 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.136 2021/07/19 22:21:36 thorpej Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -875,65 +877,65 @@ unaligned_fixup(u_long va, u_long opcode
signo = SIGSEGV;
if (dofix && selected_tab->fixable) {
switch (opcode) {
- case 0x0c: /* ldwu */
+ case op_ldwu:
/* XXX ONLY WORKS ON LITTLE-ENDIAN ALPHA */
unaligned_load_integer(worddata);
break;
- case 0x0d: /* stw */
+ case op_stw:
/* XXX ONLY WORKS ON LITTLE-ENDIAN ALPHA */
unaligned_store_integer(worddata);
break;
#ifdef FIX_UNALIGNED_VAX_FP
- case 0x20: /* ldf */
+ case op_ldf:
unaligned_load_floating(intdata, Ffloat_to_reg);
break;
- case 0x21: /* ldg */
+ case op_ldg:
unaligned_load_floating(longdata, Gfloat_reg_cvt);
break;
#endif
- case 0x22: /* lds */
+ case op_lds:
unaligned_load_floating(intdata, Sfloat_to_reg);
break;
- case 0x23: /* ldt */
+ case op_ldt:
unaligned_load_floating(longdata, Tfloat_reg_cvt);
break;
#ifdef FIX_UNALIGNED_VAX_FP
- case 0x24: /* stf */
+ case op_stf:
unaligned_store_floating(intdata, reg_to_Ffloat);
break;
- case 0x25: /* stg */
+ case op_stg:
unaligned_store_floating(longdata, Gfloat_reg_cvt);
break;
#endif
- case 0x26: /* sts */
+ case op_sts:
unaligned_store_floating(intdata, reg_to_Sfloat);
break;
- case 0x27: /* stt */
+ case op_stt:
unaligned_store_floating(longdata, Tfloat_reg_cvt);
break;
- case 0x28: /* ldl */
+ case op_ldl:
unaligned_load_integer(intdata);
break;
- case 0x29: /* ldq */
+ case op_ldq:
unaligned_load_integer(longdata);
break;
- case 0x2c: /* stl */
+ case op_stl:
unaligned_store_integer(intdata);
break;
- case 0x2d: /* stq */
+ case op_stq:
unaligned_store_integer(longdata);
break;
@@ -958,6 +960,28 @@ unaligned_fixup(u_long va, u_long opcode
return (signo);
}
+static struct evcnt emul_bwx_ldbu =
+ EVCNT_INITIALIZER(EVCNT_TYPE_TRAP, NULL, "emul bwx", "ldbu");
+static struct evcnt emul_bwx_ldwu =
+ EVCNT_INITIALIZER(EVCNT_TYPE_TRAP, NULL, "emul bwx", "ldwu");
+static struct evcnt emul_bwx_stb =
+ EVCNT_INITIALIZER(EVCNT_TYPE_TRAP, NULL, "emul bwx", "stb");
+static struct evcnt emul_bwx_stw =
+ EVCNT_INITIALIZER(EVCNT_TYPE_TRAP, NULL, "emul bwx", "stw");
+static struct evcnt emul_bwx_sextb =
+ EVCNT_INITIALIZER(EVCNT_TYPE_TRAP, NULL, "emul bwx", "sextb");
+static struct evcnt emul_bwx_sextw =
+ EVCNT_INITIALIZER(EVCNT_TYPE_TRAP, NULL, "emul bwx", "sextw");
+
+EVCNT_ATTACH_STATIC(emul_bwx_ldbu);
+EVCNT_ATTACH_STATIC(emul_bwx_ldwu);
+EVCNT_ATTACH_STATIC(emul_bwx_stb);
+EVCNT_ATTACH_STATIC(emul_bwx_stw);
+EVCNT_ATTACH_STATIC(emul_bwx_sextb);
+EVCNT_ATTACH_STATIC(emul_bwx_sextw);
+
+#define EMUL_COUNT(ev) atomic_inc_64(&(ev).ev_count)
+
/*
* Reserved/unimplemented instruction (opDec fault) handler
*
@@ -986,7 +1010,7 @@ handle_opdec(struct lwp *l, u_long *ucod
l->l_md.md_tf->tf_regs[FRAME_SP] = alpha_pal_rdusp();
inst_pc = memaddr = l->l_md.md_tf->tf_regs[FRAME_PC] - 4;
- if (copyin((void *)inst_pc, &inst, sizeof (inst)) != 0) {
+ if (ufetch_int((void *)inst_pc, &inst.bits) != 0) {
/*
* really, this should never happen, but in case it
* does we handle it.
@@ -1012,6 +1036,11 @@ handle_opdec(struct lwp *l, u_long *ucod
if (inst.mem_format.opcode == op_ldwu ||
inst.mem_format.opcode == op_stw) {
if (memaddr & 0x01) {
+ if (inst.mem_format.opcode == op_ldwu) {
+ EMUL_COUNT(emul_bwx_ldwu);
+ } else {
+ EMUL_COUNT(emul_bwx_stw);
+ }
sig = unaligned_fixup(memaddr,
inst.mem_format.opcode,
inst.mem_format.ra, l);
@@ -1021,35 +1050,42 @@ handle_opdec(struct lwp *l, u_long *ucod
}
}
+ /*
+ * We know the addresses are aligned, so it's safe to
+ * use _u{fetch,store}_{8,16}(). Note, these are
+ * __UFETCHSTORE_PRIVATE, but this is MD code, and
+ * we know the details of the alpha implementation.
+ */
+
if (inst.mem_format.opcode == op_ldbu) {
uint8_t b;
- /* XXX ONLY WORKS ON LITTLE-ENDIAN ALPHA */
- if (copyin((void *)memaddr, &b, sizeof (b)) != 0)
+ EMUL_COUNT(emul_bwx_ldbu);
+ if (_ufetch_8((void *)memaddr, &b) != 0)
goto sigsegv;
if (regptr != NULL)
*regptr = b;
} else if (inst.mem_format.opcode == op_ldwu) {
uint16_t w;
- /* XXX ONLY WORKS ON LITTLE-ENDIAN ALPHA */
- if (copyin((void *)memaddr, &w, sizeof (w)) != 0)
+ EMUL_COUNT(emul_bwx_ldwu);
+ if (_ufetch_16((void *)memaddr, &w) != 0)
goto sigsegv;
if (regptr != NULL)
*regptr = w;
} else if (inst.mem_format.opcode == op_stw) {
uint16_t w;
- /* XXX ONLY WORKS ON LITTLE-ENDIAN ALPHA */
+ EMUL_COUNT(emul_bwx_stw);
w = (regptr != NULL) ? *regptr : 0;
- if (copyout(&w, (void *)memaddr, sizeof (w)) != 0)
+ if (_ustore_16((void *)memaddr, w) != 0)
goto sigsegv;
} else if (inst.mem_format.opcode == op_stb) {
uint8_t b;
- /* XXX ONLY WORKS ON LITTLE-ENDIAN ALPHA */
+ EMUL_COUNT(emul_bwx_stb);
b = (regptr != NULL) ? *regptr : 0;
- if (copyout(&b, (void *)memaddr, sizeof (b)) != 0)
+ if (_ustore_8((void *)memaddr, b) != 0)
goto sigsegv;
}
break;
@@ -1059,6 +1095,7 @@ handle_opdec(struct lwp *l, u_long *ucod
inst.operate_generic_format.ra == 31) {
int8_t b;
+ EMUL_COUNT(emul_bwx_sextb);
if (inst.operate_generic_format.is_lit) {
b = inst.operate_lit_format.literal;
} else {
@@ -1077,6 +1114,7 @@ handle_opdec(struct lwp *l, u_long *ucod
inst.operate_generic_format.ra == 31) {
int16_t w;
+ EMUL_COUNT(emul_bwx_sextw);
if (inst.operate_generic_format.is_lit) {
w = inst.operate_lit_format.literal;
} else {