cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

fpu_entry.c (20955B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*---------------------------------------------------------------------------+
      3 |  fpu_entry.c                                                              |
      4 |                                                                           |
      5 | The entry functions for wm-FPU-emu                                        |
      6 |                                                                           |
      7 | Copyright (C) 1992,1993,1994,1996,1997                                    |
      8 |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
      9 |                  E-mail   billm@suburbia.net                              |
     10 |                                                                           |
     11 | See the files "README" and "COPYING" for further copyright and warranty   |
     12 | information.                                                              |
     13 |                                                                           |
     14 +---------------------------------------------------------------------------*/
     15
     16/*---------------------------------------------------------------------------+
     17 | Note:                                                                     |
     18 |    The file contains code which accesses user memory.                     |
     19 |    Emulator static data may change when user memory is accessed, due to   |
     20 |    other processes using the emulator while swapping is in progress.      |
     21 +---------------------------------------------------------------------------*/
     22
     23/*---------------------------------------------------------------------------+
     24 | math_emulate(), restore_i387_soft() and save_i387_soft() are the only     |
     25 | entry points for wm-FPU-emu.                                              |
     26 +---------------------------------------------------------------------------*/
     27
     28#include <linux/signal.h>
     29#include <linux/regset.h>
     30
     31#include <linux/uaccess.h>
     32#include <asm/traps.h>
     33#include <asm/user.h>
     34#include <asm/fpu/api.h>
     35
     36#include "fpu_system.h"
     37#include "fpu_emu.h"
     38#include "exception.h"
     39#include "control_w.h"
     40#include "status_w.h"
     41
     42#define __BAD__ FPU_illegal	/* Illegal on an 80486, causes SIGILL */
     43
     44/* fcmovCC and f(u)comi(p) are enabled if CPUID(1).EDX(15) "cmov" is set */
     45
     46/* WARNING: "u" entries are not documented by Intel in their 80486 manual
     47   and may not work on FPU clones or later Intel FPUs.
     48   Changes to support them provided by Linus Torvalds. */
     49
     50static FUNC const st_instr_table[64] = {
     51/* Opcode:	d8		d9		da		db */
     52/*		dc		dd		de		df */
     53/* c0..7 */	fadd__,		fld_i_,		fcmovb,		fcmovnb,
     54/* c0..7 */	fadd_i,		ffree_,		faddp_,		ffreep,/*u*/
     55/* c8..f */	fmul__,		fxch_i,		fcmove,		fcmovne,
     56/* c8..f */	fmul_i,		fxch_i,/*u*/	fmulp_,		fxch_i,/*u*/
     57/* d0..7 */	fcom_st,	fp_nop,		fcmovbe,	fcmovnbe,
     58/* d0..7 */	fcom_st,/*u*/	fst_i_,		fcompst,/*u*/	fstp_i,/*u*/
     59/* d8..f */	fcompst,	fstp_i,/*u*/	fcmovu,		fcmovnu,
     60/* d8..f */	fcompst,/*u*/	fstp_i,		fcompp,		fstp_i,/*u*/
     61/* e0..7 */	fsub__,		FPU_etc,	__BAD__,	finit_,
     62/* e0..7 */	fsubri,		fucom_,		fsubrp,		fstsw_,
     63/* e8..f */	fsubr_,		fconst,		fucompp,	fucomi_,
     64/* e8..f */	fsub_i,		fucomp,		fsubp_,		fucomip,
     65/* f0..7 */	fdiv__,		FPU_triga,	__BAD__,	fcomi_,
     66/* f0..7 */	fdivri,		__BAD__,	fdivrp,		fcomip,
     67/* f8..f */	fdivr_,		FPU_trigb,	__BAD__,	__BAD__,
     68/* f8..f */	fdiv_i,		__BAD__,	fdivp_,		__BAD__,
     69};
     70
     71#define _NONE_ 0		/* Take no special action */
     72#define _REG0_ 1		/* Need to check for not empty st(0) */
     73#define _REGI_ 2		/* Need to check for not empty st(0) and st(rm) */
     74#define _REGi_ 0		/* Uses st(rm) */
     75#define _PUSH_ 3		/* Need to check for space to push onto stack */
     76#define _null_ 4		/* Function illegal or not implemented */
     77#define _REGIi 5		/* Uses st(0) and st(rm), result to st(rm) */
     78#define _REGIp 6		/* Uses st(0) and st(rm), result to st(rm) then pop */
     79#define _REGIc 0		/* Compare st(0) and st(rm) */
     80#define _REGIn 0		/* Uses st(0) and st(rm), but handle checks later */
     81
     82static u_char const type_table[64] = {
     83/* Opcode:	d8	d9	da	db	dc	dd	de	df */
     84/* c0..7 */	_REGI_, _NONE_, _REGIn, _REGIn, _REGIi, _REGi_, _REGIp, _REGi_,
     85/* c8..f */	_REGI_, _REGIn, _REGIn, _REGIn, _REGIi, _REGI_, _REGIp, _REGI_,
     86/* d0..7 */	_REGIc, _NONE_, _REGIn, _REGIn, _REGIc, _REG0_, _REGIc, _REG0_,
     87/* d8..f */	_REGIc, _REG0_, _REGIn, _REGIn, _REGIc, _REG0_, _REGIc, _REG0_,
     88/* e0..7 */	_REGI_, _NONE_, _null_, _NONE_, _REGIi, _REGIc, _REGIp, _NONE_,
     89/* e8..f */	_REGI_, _NONE_, _REGIc, _REGIc, _REGIi, _REGIc, _REGIp, _REGIc,
     90/* f0..7 */	_REGI_, _NONE_, _null_, _REGIc, _REGIi, _null_, _REGIp, _REGIc,
     91/* f8..f */	_REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_,
     92};
     93
     94#ifdef RE_ENTRANT_CHECKING
     95u_char emulating = 0;
     96#endif /* RE_ENTRANT_CHECKING */
     97
     98static int valid_prefix(u_char *Byte, u_char __user ** fpu_eip,
     99			overrides * override);
    100
    101void math_emulate(struct math_emu_info *info)
    102{
    103	u_char FPU_modrm, byte1;
    104	unsigned short code;
    105	fpu_addr_modes addr_modes;
    106	int unmasked;
    107	FPU_REG loaded_data;
    108	FPU_REG *st0_ptr;
    109	u_char loaded_tag, st0_tag;
    110	void __user *data_address;
    111	struct address data_sel_off;
    112	struct address entry_sel_off;
    113	unsigned long code_base = 0;
    114	unsigned long code_limit = 0;	/* Initialized to stop compiler warnings */
    115	struct desc_struct code_descriptor;
    116
    117#ifdef RE_ENTRANT_CHECKING
    118	if (emulating) {
    119		printk("ERROR: wm-FPU-emu is not RE-ENTRANT!\n");
    120	}
    121	RE_ENTRANT_CHECK_ON;
    122#endif /* RE_ENTRANT_CHECKING */
    123
    124	FPU_info = info;
    125
    126	FPU_ORIG_EIP = FPU_EIP;
    127
    128	if ((FPU_EFLAGS & 0x00020000) != 0) {
    129		/* Virtual 8086 mode */
    130		addr_modes.default_mode = VM86;
    131		FPU_EIP += code_base = FPU_CS << 4;
    132		code_limit = code_base + 0xffff;	/* Assumes code_base <= 0xffff0000 */
    133	} else if (FPU_CS == __USER_CS && FPU_DS == __USER_DS) {
    134		addr_modes.default_mode = 0;
    135	} else if (FPU_CS == __KERNEL_CS) {
    136		printk("math_emulate: %04x:%08lx\n", FPU_CS, FPU_EIP);
    137		panic("Math emulation needed in kernel");
    138	} else {
    139
    140		if ((FPU_CS & 4) != 4) {	/* Must be in the LDT */
    141			/* Can only handle segmented addressing via the LDT
    142			   for now, and it must be 16 bit */
    143			printk("FPU emulator: Unsupported addressing mode\n");
    144			math_abort(FPU_info, SIGILL);
    145		}
    146
    147		code_descriptor = FPU_get_ldt_descriptor(FPU_CS);
    148		if (code_descriptor.d) {
    149			/* The above test may be wrong, the book is not clear */
    150			/* Segmented 32 bit protected mode */
    151			addr_modes.default_mode = SEG32;
    152		} else {
    153			/* 16 bit protected mode */
    154			addr_modes.default_mode = PM16;
    155		}
    156		FPU_EIP += code_base = seg_get_base(&code_descriptor);
    157		code_limit = seg_get_limit(&code_descriptor) + 1;
    158		code_limit *= seg_get_granularity(&code_descriptor);
    159		code_limit += code_base - 1;
    160		if (code_limit < code_base)
    161			code_limit = 0xffffffff;
    162	}
    163
    164	FPU_lookahead = !(FPU_EFLAGS & X86_EFLAGS_TF);
    165
    166	if (!valid_prefix(&byte1, (u_char __user **) & FPU_EIP,
    167			  &addr_modes.override)) {
    168		RE_ENTRANT_CHECK_OFF;
    169		printk
    170		    ("FPU emulator: Unknown prefix byte 0x%02x, probably due to\n"
    171		     "FPU emulator: self-modifying code! (emulation impossible)\n",
    172		     byte1);
    173		RE_ENTRANT_CHECK_ON;
    174		EXCEPTION(EX_INTERNAL | 0x126);
    175		math_abort(FPU_info, SIGILL);
    176	}
    177
    178      do_another_FPU_instruction:
    179
    180	no_ip_update = 0;
    181
    182	FPU_EIP++;		/* We have fetched the prefix and first code bytes. */
    183
    184	if (addr_modes.default_mode) {
    185		/* This checks for the minimum instruction bytes.
    186		   We also need to check any extra (address mode) code access. */
    187		if (FPU_EIP > code_limit)
    188			math_abort(FPU_info, SIGSEGV);
    189	}
    190
    191	if ((byte1 & 0xf8) != 0xd8) {
    192		if (byte1 == FWAIT_OPCODE) {
    193			if (partial_status & SW_Summary)
    194				goto do_the_FPU_interrupt;
    195			else
    196				goto FPU_fwait_done;
    197		}
    198#ifdef PARANOID
    199		EXCEPTION(EX_INTERNAL | 0x128);
    200		math_abort(FPU_info, SIGILL);
    201#endif /* PARANOID */
    202	}
    203
    204	RE_ENTRANT_CHECK_OFF;
    205	FPU_code_access_ok(1);
    206	FPU_get_user(FPU_modrm, (u_char __user *) FPU_EIP);
    207	RE_ENTRANT_CHECK_ON;
    208	FPU_EIP++;
    209
    210	if (partial_status & SW_Summary) {
    211		/* Ignore the error for now if the current instruction is a no-wait
    212		   control instruction */
    213		/* The 80486 manual contradicts itself on this topic,
    214		   but a real 80486 uses the following instructions:
    215		   fninit, fnstenv, fnsave, fnstsw, fnstenv, fnclex.
    216		 */
    217		code = (FPU_modrm << 8) | byte1;
    218		if (!((((code & 0xf803) == 0xe003) ||	/* fnclex, fninit, fnstsw */
    219		       (((code & 0x3003) == 0x3001) &&	/* fnsave, fnstcw, fnstenv,
    220							   fnstsw */
    221			((code & 0xc000) != 0xc000))))) {
    222			/*
    223			 *  We need to simulate the action of the kernel to FPU
    224			 *  interrupts here.
    225			 */
    226		      do_the_FPU_interrupt:
    227
    228			FPU_EIP = FPU_ORIG_EIP;	/* Point to current FPU instruction. */
    229
    230			RE_ENTRANT_CHECK_OFF;
    231			current->thread.trap_nr = X86_TRAP_MF;
    232			current->thread.error_code = 0;
    233			send_sig(SIGFPE, current, 1);
    234			return;
    235		}
    236	}
    237
    238	entry_sel_off.offset = FPU_ORIG_EIP;
    239	entry_sel_off.selector = FPU_CS;
    240	entry_sel_off.opcode = (byte1 << 8) | FPU_modrm;
    241	entry_sel_off.empty = 0;
    242
    243	FPU_rm = FPU_modrm & 7;
    244
    245	if (FPU_modrm < 0300) {
    246		/* All of these instructions use the mod/rm byte to get a data address */
    247
    248		if ((addr_modes.default_mode & SIXTEEN)
    249		    ^ (addr_modes.override.address_size == ADDR_SIZE_PREFIX))
    250			data_address =
    251			    FPU_get_address_16(FPU_modrm, &FPU_EIP,
    252					       &data_sel_off, addr_modes);
    253		else
    254			data_address =
    255			    FPU_get_address(FPU_modrm, &FPU_EIP, &data_sel_off,
    256					    addr_modes);
    257
    258		if (addr_modes.default_mode) {
    259			if (FPU_EIP - 1 > code_limit)
    260				math_abort(FPU_info, SIGSEGV);
    261		}
    262
    263		if (!(byte1 & 1)) {
    264			unsigned short status1 = partial_status;
    265
    266			st0_ptr = &st(0);
    267			st0_tag = FPU_gettag0();
    268
    269			/* Stack underflow has priority */
    270			if (NOT_EMPTY_ST0) {
    271				if (addr_modes.default_mode & PROTECTED) {
    272					/* This table works for 16 and 32 bit protected mode */
    273					if (access_limit <
    274					    data_sizes_16[(byte1 >> 1) & 3])
    275						math_abort(FPU_info, SIGSEGV);
    276				}
    277
    278				unmasked = 0;	/* Do this here to stop compiler warnings. */
    279				switch ((byte1 >> 1) & 3) {
    280				case 0:
    281					unmasked =
    282					    FPU_load_single((float __user *)
    283							    data_address,
    284							    &loaded_data);
    285					loaded_tag = unmasked & 0xff;
    286					unmasked &= ~0xff;
    287					break;
    288				case 1:
    289					loaded_tag =
    290					    FPU_load_int32((long __user *)
    291							   data_address,
    292							   &loaded_data);
    293					break;
    294				case 2:
    295					unmasked =
    296					    FPU_load_double((double __user *)
    297							    data_address,
    298							    &loaded_data);
    299					loaded_tag = unmasked & 0xff;
    300					unmasked &= ~0xff;
    301					break;
    302				case 3:
    303				default:	/* Used here to suppress gcc warnings. */
    304					loaded_tag =
    305					    FPU_load_int16((short __user *)
    306							   data_address,
    307							   &loaded_data);
    308					break;
    309				}
    310
    311				/* No more access to user memory, it is safe
    312				   to use static data now */
    313
    314				/* NaN operands have the next priority. */
    315				/* We have to delay looking at st(0) until after
    316				   loading the data, because that data might contain an SNaN */
    317				if (((st0_tag == TAG_Special) && isNaN(st0_ptr))
    318				    || ((loaded_tag == TAG_Special)
    319					&& isNaN(&loaded_data))) {
    320					/* Restore the status word; we might have loaded a
    321					   denormal. */
    322					partial_status = status1;
    323					if ((FPU_modrm & 0x30) == 0x10) {
    324						/* fcom or fcomp */
    325						EXCEPTION(EX_Invalid);
    326						setcc(SW_C3 | SW_C2 | SW_C0);
    327						if ((FPU_modrm & 0x08)
    328						    && (control_word &
    329							CW_Invalid))
    330							FPU_pop();	/* fcomp, masked, so we pop. */
    331					} else {
    332						if (loaded_tag == TAG_Special)
    333							loaded_tag =
    334							    FPU_Special
    335							    (&loaded_data);
    336#ifdef PECULIAR_486
    337						/* This is not really needed, but gives behaviour
    338						   identical to an 80486 */
    339						if ((FPU_modrm & 0x28) == 0x20)
    340							/* fdiv or fsub */
    341							real_2op_NaN
    342							    (&loaded_data,
    343							     loaded_tag, 0,
    344							     &loaded_data);
    345						else
    346#endif /* PECULIAR_486 */
    347							/* fadd, fdivr, fmul, or fsubr */
    348							real_2op_NaN
    349							    (&loaded_data,
    350							     loaded_tag, 0,
    351							     st0_ptr);
    352					}
    353					goto reg_mem_instr_done;
    354				}
    355
    356				if (unmasked && !((FPU_modrm & 0x30) == 0x10)) {
    357					/* Is not a comparison instruction. */
    358					if ((FPU_modrm & 0x38) == 0x38) {
    359						/* fdivr */
    360						if ((st0_tag == TAG_Zero) &&
    361						    ((loaded_tag == TAG_Valid)
    362						     || (loaded_tag ==
    363							 TAG_Special
    364							 &&
    365							 isdenormal
    366							 (&loaded_data)))) {
    367							if (FPU_divide_by_zero
    368							    (0,
    369							     getsign
    370							     (&loaded_data))
    371							    < 0) {
    372								/* We use the fact here that the unmasked
    373								   exception in the loaded data was for a
    374								   denormal operand */
    375								/* Restore the state of the denormal op bit */
    376								partial_status
    377								    &=
    378								    ~SW_Denorm_Op;
    379								partial_status
    380								    |=
    381								    status1 &
    382								    SW_Denorm_Op;
    383							} else
    384								setsign(st0_ptr,
    385									getsign
    386									(&loaded_data));
    387						}
    388					}
    389					goto reg_mem_instr_done;
    390				}
    391
    392				switch ((FPU_modrm >> 3) & 7) {
    393				case 0:	/* fadd */
    394					clear_C1();
    395					FPU_add(&loaded_data, loaded_tag, 0,
    396						control_word);
    397					break;
    398				case 1:	/* fmul */
    399					clear_C1();
    400					FPU_mul(&loaded_data, loaded_tag, 0,
    401						control_word);
    402					break;
    403				case 2:	/* fcom */
    404					FPU_compare_st_data(&loaded_data,
    405							    loaded_tag);
    406					break;
    407				case 3:	/* fcomp */
    408					if (!FPU_compare_st_data
    409					    (&loaded_data, loaded_tag)
    410					    && !unmasked)
    411						FPU_pop();
    412					break;
    413				case 4:	/* fsub */
    414					clear_C1();
    415					FPU_sub(LOADED | loaded_tag,
    416						(int)&loaded_data,
    417						control_word);
    418					break;
    419				case 5:	/* fsubr */
    420					clear_C1();
    421					FPU_sub(REV | LOADED | loaded_tag,
    422						(int)&loaded_data,
    423						control_word);
    424					break;
    425				case 6:	/* fdiv */
    426					clear_C1();
    427					FPU_div(LOADED | loaded_tag,
    428						(int)&loaded_data,
    429						control_word);
    430					break;
    431				case 7:	/* fdivr */
    432					clear_C1();
    433					if (st0_tag == TAG_Zero)
    434						partial_status = status1;	/* Undo any denorm tag,
    435										   zero-divide has priority. */
    436					FPU_div(REV | LOADED | loaded_tag,
    437						(int)&loaded_data,
    438						control_word);
    439					break;
    440				}
    441			} else {
    442				if ((FPU_modrm & 0x30) == 0x10) {
    443					/* The instruction is fcom or fcomp */
    444					EXCEPTION(EX_StackUnder);
    445					setcc(SW_C3 | SW_C2 | SW_C0);
    446					if ((FPU_modrm & 0x08)
    447					    && (control_word & CW_Invalid))
    448						FPU_pop();	/* fcomp */
    449				} else
    450					FPU_stack_underflow();
    451			}
    452		      reg_mem_instr_done:
    453			operand_address = data_sel_off;
    454		} else {
    455			if (!(no_ip_update =
    456			      FPU_load_store(((FPU_modrm & 0x38) | (byte1 & 6))
    457					     >> 1, addr_modes, data_address))) {
    458				operand_address = data_sel_off;
    459			}
    460		}
    461
    462	} else {
    463		/* None of these instructions access user memory */
    464		u_char instr_index = (FPU_modrm & 0x38) | (byte1 & 7);
    465
    466#ifdef PECULIAR_486
    467		/* This is supposed to be undefined, but a real 80486 seems
    468		   to do this: */
    469		operand_address.offset = 0;
    470		operand_address.selector = FPU_DS;
    471#endif /* PECULIAR_486 */
    472
    473		st0_ptr = &st(0);
    474		st0_tag = FPU_gettag0();
    475		switch (type_table[(int)instr_index]) {
    476		case _NONE_:	/* also _REGIc: _REGIn */
    477			break;
    478		case _REG0_:
    479			if (!NOT_EMPTY_ST0) {
    480				FPU_stack_underflow();
    481				goto FPU_instruction_done;
    482			}
    483			break;
    484		case _REGIi:
    485			if (!NOT_EMPTY_ST0 || !NOT_EMPTY(FPU_rm)) {
    486				FPU_stack_underflow_i(FPU_rm);
    487				goto FPU_instruction_done;
    488			}
    489			break;
    490		case _REGIp:
    491			if (!NOT_EMPTY_ST0 || !NOT_EMPTY(FPU_rm)) {
    492				FPU_stack_underflow_pop(FPU_rm);
    493				goto FPU_instruction_done;
    494			}
    495			break;
    496		case _REGI_:
    497			if (!NOT_EMPTY_ST0 || !NOT_EMPTY(FPU_rm)) {
    498				FPU_stack_underflow();
    499				goto FPU_instruction_done;
    500			}
    501			break;
    502		case _PUSH_:	/* Only used by the fld st(i) instruction */
    503			break;
    504		case _null_:
    505			FPU_illegal();
    506			goto FPU_instruction_done;
    507		default:
    508			EXCEPTION(EX_INTERNAL | 0x111);
    509			goto FPU_instruction_done;
    510		}
    511		(*st_instr_table[(int)instr_index]) ();
    512
    513	      FPU_instruction_done:
    514		;
    515	}
    516
    517	if (!no_ip_update)
    518		instruction_address = entry_sel_off;
    519
    520      FPU_fwait_done:
    521
    522#ifdef DEBUG
    523	RE_ENTRANT_CHECK_OFF;
    524	FPU_printall();
    525	RE_ENTRANT_CHECK_ON;
    526#endif /* DEBUG */
    527
    528	if (FPU_lookahead && !need_resched()) {
    529		FPU_ORIG_EIP = FPU_EIP - code_base;
    530		if (valid_prefix(&byte1, (u_char __user **) & FPU_EIP,
    531				 &addr_modes.override))
    532			goto do_another_FPU_instruction;
    533	}
    534
    535	if (addr_modes.default_mode)
    536		FPU_EIP -= code_base;
    537
    538	RE_ENTRANT_CHECK_OFF;
    539}
    540
    541/* Support for prefix bytes is not yet complete. To properly handle
    542   all prefix bytes, further changes are needed in the emulator code
    543   which accesses user address space. Access to separate segments is
    544   important for msdos emulation. */
    545static int valid_prefix(u_char *Byte, u_char __user **fpu_eip,
    546			overrides * override)
    547{
    548	u_char byte;
    549	u_char __user *ip = *fpu_eip;
    550
    551	*override = (overrides) {
    552	0, 0, PREFIX_DEFAULT};	/* defaults */
    553
    554	RE_ENTRANT_CHECK_OFF;
    555	FPU_code_access_ok(1);
    556	FPU_get_user(byte, ip);
    557	RE_ENTRANT_CHECK_ON;
    558
    559	while (1) {
    560		switch (byte) {
    561		case ADDR_SIZE_PREFIX:
    562			override->address_size = ADDR_SIZE_PREFIX;
    563			goto do_next_byte;
    564
    565		case OP_SIZE_PREFIX:
    566			override->operand_size = OP_SIZE_PREFIX;
    567			goto do_next_byte;
    568
    569		case PREFIX_CS:
    570			override->segment = PREFIX_CS_;
    571			goto do_next_byte;
    572		case PREFIX_ES:
    573			override->segment = PREFIX_ES_;
    574			goto do_next_byte;
    575		case PREFIX_SS:
    576			override->segment = PREFIX_SS_;
    577			goto do_next_byte;
    578		case PREFIX_FS:
    579			override->segment = PREFIX_FS_;
    580			goto do_next_byte;
    581		case PREFIX_GS:
    582			override->segment = PREFIX_GS_;
    583			goto do_next_byte;
    584		case PREFIX_DS:
    585			override->segment = PREFIX_DS_;
    586			goto do_next_byte;
    587
    588/* lock is not a valid prefix for FPU instructions,
    589   let the cpu handle it to generate a SIGILL. */
    590/*	case PREFIX_LOCK: */
    591
    592			/* rep.. prefixes have no meaning for FPU instructions */
    593		case PREFIX_REPE:
    594		case PREFIX_REPNE:
    595
    596		      do_next_byte:
    597			ip++;
    598			RE_ENTRANT_CHECK_OFF;
    599			FPU_code_access_ok(1);
    600			FPU_get_user(byte, ip);
    601			RE_ENTRANT_CHECK_ON;
    602			break;
    603		case FWAIT_OPCODE:
    604			*Byte = byte;
    605			return 1;
    606		default:
    607			if ((byte & 0xf8) == 0xd8) {
    608				*Byte = byte;
    609				*fpu_eip = ip;
    610				return 1;
    611			} else {
    612				/* Not a valid sequence of prefix bytes followed by
    613				   an FPU instruction. */
    614				*Byte = byte;	/* Needed for error message. */
    615				return 0;
    616			}
    617		}
    618	}
    619}
    620
    621void math_abort(struct math_emu_info *info, unsigned int signal)
    622{
    623	FPU_EIP = FPU_ORIG_EIP;
    624	current->thread.trap_nr = X86_TRAP_MF;
    625	current->thread.error_code = 0;
    626	send_sig(signal, current, 1);
    627	RE_ENTRANT_CHECK_OFF;
    628      __asm__("movl %0,%%esp ; ret": :"g"(((long)info) - 4));
    629#ifdef PARANOID
    630	printk("ERROR: wm-FPU-emu math_abort failed!\n");
    631#endif /* PARANOID */
    632}
    633
    634#define S387 ((struct swregs_state *)s387)
    635#define sstatus_word() \
    636  ((S387->swd & ~SW_Top & 0xffff) | ((S387->ftop << SW_Top_Shift) & SW_Top))
    637
    638int fpregs_soft_set(struct task_struct *target,
    639		    const struct user_regset *regset,
    640		    unsigned int pos, unsigned int count,
    641		    const void *kbuf, const void __user *ubuf)
    642{
    643	struct swregs_state *s387 = &target->thread.fpu.fpstate->regs.soft;
    644	void *space = s387->st_space;
    645	int ret;
    646	int offset, other, i, tags, regnr, tag, newtop;
    647
    648	RE_ENTRANT_CHECK_OFF;
    649	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, s387, 0,
    650				 offsetof(struct swregs_state, st_space));
    651	RE_ENTRANT_CHECK_ON;
    652
    653	if (ret)
    654		return ret;
    655
    656	S387->ftop = (S387->swd >> SW_Top_Shift) & 7;
    657	offset = (S387->ftop & 7) * 10;
    658	other = 80 - offset;
    659
    660	RE_ENTRANT_CHECK_OFF;
    661
    662	/* Copy all registers in stack order. */
    663	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
    664				 space + offset, 0, other);
    665	if (!ret && offset)
    666		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
    667					 space, 0, offset);
    668
    669	RE_ENTRANT_CHECK_ON;
    670
    671	/* The tags may need to be corrected now. */
    672	tags = S387->twd;
    673	newtop = S387->ftop;
    674	for (i = 0; i < 8; i++) {
    675		regnr = (i + newtop) & 7;
    676		if (((tags >> ((regnr & 7) * 2)) & 3) != TAG_Empty) {
    677			/* The loaded data over-rides all other cases. */
    678			tag =
    679			    FPU_tagof((FPU_REG *) ((u_char *) S387->st_space +
    680						   10 * regnr));
    681			tags &= ~(3 << (regnr * 2));
    682			tags |= (tag & 3) << (regnr * 2);
    683		}
    684	}
    685	S387->twd = tags;
    686
    687	return ret;
    688}
    689
    690int fpregs_soft_get(struct task_struct *target,
    691		    const struct user_regset *regset,
    692		    struct membuf to)
    693{
    694	struct swregs_state *s387 = &target->thread.fpu.fpstate->regs.soft;
    695	const void *space = s387->st_space;
    696	int offset = (S387->ftop & 7) * 10, other = 80 - offset;
    697
    698	RE_ENTRANT_CHECK_OFF;
    699
    700#ifdef PECULIAR_486
    701	S387->cwd &= ~0xe080;
    702	/* An 80486 sets nearly all of the reserved bits to 1. */
    703	S387->cwd |= 0xffff0040;
    704	S387->swd = sstatus_word() | 0xffff0000;
    705	S387->twd |= 0xffff0000;
    706	S387->fcs &= ~0xf8000000;
    707	S387->fos |= 0xffff0000;
    708#endif /* PECULIAR_486 */
    709
    710	membuf_write(&to, s387, offsetof(struct swregs_state, st_space));
    711	membuf_write(&to, space + offset, other);
    712	membuf_write(&to, space, offset);
    713
    714	RE_ENTRANT_CHECK_ON;
    715
    716	return 0;
    717}