Module Name: src
Committed By: isaki
Date: Mon Jan 6 07:34:24 UTC 2025
Modified Files:
src/sys/arch/m68k/fpe: fpu_emulate.c fpu_fscale.c
Log Message:
m68k/fpe: Avoid an illegal mod/reg before decoding it.
This also works for machines with FPU.
If the kernel defines FPU_EMULATE, even illegal FPU instructions in the real
6888x machines, the FPE will be executed by F line exception. So the FPE
must raise SIGILL appropriately for these.
To generate a diff of this commit:
cvs rdiff -u -r1.48 -r1.49 src/sys/arch/m68k/fpe/fpu_emulate.c
cvs rdiff -u -r1.16 -r1.17 src/sys/arch/m68k/fpe/fpu_fscale.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/m68k/fpe/fpu_emulate.c
diff -u src/sys/arch/m68k/fpe/fpu_emulate.c:1.48 src/sys/arch/m68k/fpe/fpu_emulate.c:1.49
--- src/sys/arch/m68k/fpe/fpu_emulate.c:1.48 Sat Dec 28 12:23:51 2024
+++ src/sys/arch/m68k/fpe/fpu_emulate.c Mon Jan 6 07:34:24 2025
@@ -1,4 +1,4 @@
-/* $NetBSD: fpu_emulate.c,v 1.48 2024/12/28 12:23:51 isaki Exp $ */
+/* $NetBSD: fpu_emulate.c,v 1.49 2025/01/06 07:34:24 isaki Exp $ */
/*
* Copyright (c) 1995 Gordon W. Ross
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fpu_emulate.c,v 1.48 2024/12/28 12:23:51 isaki Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fpu_emulate.c,v 1.49 2025/01/06 07:34:24 isaki Exp $");
#include <sys/param.h>
#include <sys/types.h>
@@ -338,10 +338,28 @@ fpu_emul_fmovmcr(struct fpemu *fe, struc
int reglist;
int regcount;
int fpu_to_mem;
+ int modreg;
uint32_t tmp[3];
/* move to/from control registers */
reglist = (insn->is_word1 & 0x1c00) >> 10;
+ /* Bit 13 selects direction (FPU to/from Mem) */
+ fpu_to_mem = insn->is_word1 & 0x2000;
+
+ /* Check an illegal mod/reg. */
+ modreg = insn->is_opcode & 077;
+ if (fpu_to_mem) {
+ /* PCrel, #imm are illegal. */
+ if (modreg >= 072) {
+ return SIGILL;
+ }
+ } else {
+ /* All mod/reg can be specified. */
+ if (modreg >= 075) {
+ return SIGILL;
+ }
+ }
+
/*
* If reglist is 0b000, treat it as FPIAR. This is not specification
* but the behavior described in the 6888x user's manual.
@@ -357,7 +375,7 @@ fpu_emul_fmovmcr(struct fpemu *fe, struc
regcount = 1;
}
insn->is_datasize = regcount * 4;
- sig = fpu_decode_ea(frame, insn, &insn->is_ea, insn->is_opcode);
+ sig = fpu_decode_ea(frame, insn, &insn->is_ea, modreg);
if (sig)
return sig;
@@ -377,8 +395,6 @@ fpu_emul_fmovmcr(struct fpemu *fe, struc
}
}
- /* Bit 13 selects direction (FPU to/from Mem) */
- fpu_to_mem = insn->is_word1 & 0x2000;
if (fpu_to_mem) {
uint32_t *s = &tmp[0];
@@ -432,6 +448,7 @@ fpu_emul_fmovm(struct fpemu *fe, struct
struct fpframe *fpf = fe->fe_fpframe;
int word1, sig;
int reglist, regmask, regnum;
+ int modreg;
int fpu_to_mem, order;
/* int w1_post_incr; */
int *fpregs;
@@ -458,8 +475,22 @@ fpu_emul_fmovm(struct fpemu *fe, struct
}
reglist &= 0xFF;
- /* Get effective address. (modreg=opcode&077) */
- sig = fpu_decode_ea(frame, insn, &insn->is_ea, insn->is_opcode);
+ /* Check an illegal mod/reg. */
+ modreg = insn->is_opcode & 077;
+ if (fpu_to_mem) {
+ /* Dn, An, (An)+, PCrel, #imm are illegal. */
+ if (modreg < 020 || (modreg >> 3) == 3 || modreg >= 072) {
+ return SIGILL;
+ }
+ } else {
+ /* Dn, An, -(An), #imm are illegal. */
+ if (modreg < 020 || (modreg >> 3) == 4 || modreg >= 074) {
+ return SIGILL;
+ }
+ }
+
+ /* Get effective address. */
+ sig = fpu_decode_ea(frame, insn, &insn->is_ea, modreg);
if (sig)
return sig;
@@ -571,6 +602,7 @@ fpu_emul_arith(struct fpemu *fe, struct
struct fpn *res;
int word1, sig = 0;
int regnum, format;
+ int modreg;
int discard_result = 0;
uint32_t buf[3];
#ifdef DEBUG_FPE
@@ -624,13 +656,26 @@ fpu_emul_arith(struct fpemu *fe, struct
return sig;
}
- /* Get effective address. (modreg=opcode&077) */
- sig = fpu_decode_ea(frame, insn, &insn->is_ea, insn->is_opcode);
+ /* Check an illegal mod/reg. */
+ modreg = insn->is_opcode & 077;
+ if ((modreg >> 3) == 1/*An*/ || modreg >= 075) {
+ return SIGILL;
+ }
+
+ /* Get effective address. */
+ sig = fpu_decode_ea(frame, insn, &insn->is_ea, modreg);
if (sig) {
DPRINTF(("%s: error in fpu_decode_ea\n", __func__));
return sig;
}
+ if (insn->is_ea.ea_flags == EA_DIRECT &&
+ insn->is_datasize > 4) {
+ DPRINTF(("%s: attempted to fetch dbl/ext from reg\n",
+ __func__));
+ return SIGILL;
+ }
+
DUMP_INSN(insn);
#ifdef DEBUG_FPE
Index: src/sys/arch/m68k/fpe/fpu_fscale.c
diff -u src/sys/arch/m68k/fpe/fpu_fscale.c:1.16 src/sys/arch/m68k/fpe/fpu_fscale.c:1.17
--- src/sys/arch/m68k/fpe/fpu_fscale.c:1.16 Tue Mar 26 11:30:20 2013
+++ src/sys/arch/m68k/fpe/fpu_fscale.c Mon Jan 6 07:34:24 2025
@@ -1,4 +1,4 @@
-/* $NetBSD: fpu_fscale.c,v 1.16 2013/03/26 11:30:20 isaki Exp $ */
+/* $NetBSD: fpu_fscale.c,v 1.17 2025/01/06 07:34:24 isaki Exp $ */
/*
* Copyright (c) 1995 Ken Nakata
@@ -38,7 +38,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fpu_fscale.c,v 1.16 2013/03/26 11:30:20 isaki Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fpu_fscale.c,v 1.17 2025/01/06 07:34:24 isaki Exp $");
#include <sys/types.h>
#include <sys/signal.h>
@@ -54,6 +54,7 @@ fpu_emul_fscale(struct fpemu *fe, struct
uint32_t *fpregs;
int word1, sig;
int regnum, format;
+ int modreg;
int scale, sign, exp;
uint32_t m0, m1;
uint32_t buf[3], fpsr;
@@ -109,6 +110,12 @@ fpu_emul_fscale(struct fpemu *fe, struct
return sig;
}
+ /* Check an illegal mod/reg. */
+ modreg = insn->is_opcode & 077;
+ if ((modreg >> 3) == 1/*An*/ || modreg >= 075) {
+ return SIGILL;
+ }
+
/* Get effective address. (modreg=opcode&077) */
sig = fpu_decode_ea(frame, insn, &insn->is_ea, insn->is_opcode);
if (sig) {
@@ -118,6 +125,15 @@ fpu_emul_fscale(struct fpemu *fe, struct
return sig;
}
+ if (insn->is_ea.ea_flags == EA_DIRECT &&
+ insn->is_datasize > 4) {
+#if DEBUG_FPE
+ printf("%s: attempted to fetch dbl/ext from reg\n",
+ __func__);
+#endif
+ return SIGILL;
+ }
+
#if DEBUG_FPE
printf("fpu_emul_fscale: addr mode = ");
flags = insn->is_ea.ea_flags;