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;