summaryrefslogtreecommitdiff
path: root/sys/arch/x86/include/cpu_extended_state.h
blob: b75661d361b2798e613dd05342da7a6d906fecbf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
/*	$NetBSD: cpu_extended_state.h,v 1.9 2014/02/25 22:16:52 dsl Exp $	*/

#ifndef _X86_CPU_EXTENDED_STATE_H_
#define _X86_CPU_EXTENDED_STATE_H_

/*
 * This file contains definitions of structures that match the memory
 * layouts used x86 processors to save floating point registers and other
 * extended cpu state.
 * This includes registers (etc) used by SSE/SSE2/SSE3/SSSE3/SSE4 and
 * the later AVX instructions.
 * The definitions are such that any future 'extended state' should
 * be handled (provided the kernel doesn't need to know the actual contents.
 *
 * The actual structures the cpu accesses must be aligned to 16 for
 * FXSAVE and 64 for XSAVE. The types aren't aligned because copies
 * do not need extra alignment.
 *
 * The slightly different layout saved by the i387 fsave in also defined.
 * This is only normally written by pre Pentium II type cpus that don't 
 * support the fxsave instruction.  
 *
 * Associated save instructions:
 * FNSAVE:  Saves x87 state in 108 bytes (original i387 layout).
 *          Then reinitialies the fpu.
 * FSAVE:   Encodes to FWAIT followed by FNSAVE.
 * FXSAVE:  Saves the x87 state and XMM (aka SSE) registers to the
 *          first 448 (max) bytes of a 512 byte area.
 *          This layout does not match that written by FNSAVE.
 * XSAVE:   Uses the same layout for the x87 and XMM registers,
 *          followed by a 64byte header and separate save areas
 *          for additional extended cpu state.
 *          The x87 state is always saved, the others conditionally.
 * XSAVEOPT: As XSAVE but (IIRC) only writes the registers blocks
 *          that have been modified.
 */

#ifdef __lint__
/* Lint has different packing rules and doesn't understand __aligned() */
#define __CTASSERT_NOLINT(x) __CTASSERT(1)
#else
#define __CTASSERT_NOLINT(x) __CTASSERT(x)
#endif

/*
 * Layout for code/data pointers relating to FP exceptions.
 * Marked 'packed' because they aren't always 64bit aligned.
 * Since the x86 cpu supports misaligned accesses it isn't
 * worth avoiding the 'packed' attribute.
 */
union fp_addr {
	uint64_t fa_64;	/* Linear address for 64bit systems */
	struct {
		uint32_t fa_off;	/* linear address for 32 bit */
		uint16_t fa_seg;	/* code/data (etc) segment */
		uint16_t fa_opcode;	/* last opcode (sometimes) */
	} fa_32;
} __packed __aligned(4);

/* The x87 registers are 80 bits */
struct fpacc87 {
	uint64_t	f87_mantissa;	/* mantissa */
	uint16_t	f87_exp_sign;	/* exponent and sign */
} __packed __aligned(2);

/* The x87 registers padded out to 16 bytes for fxsave */
struct fpaccfx {
	struct fpacc87 r __aligned(16);
};

/* The SSE/SSE2 registers are 128 bits */
struct xmmreg {
	uint8_t xmm_bytes[16];
};

/* The AVX registers are 256 bits, but the low bits are the xmmregs */
struct ymmreg {
	uint8_t ymm_bytes[16];
};

/*
 * Floating point unit registers (fsave instruction).
 * The s87_ac[] and fx_87_ac[] are relative to the stack top.
 * The 'tag word' contains 2 bits per register and refers to
 * absolute register numbers.
 * The cpu sets the tag values 0b01 (zero) and 0b10 (special) when a value
 * is loaded. The software need only set 0b00 (used) and 0xb11 (unused).
 * The fxsave 'Abridged tag word' in inverted.
 */
struct save87 {
	uint16_t	s87_cw __aligned(4);	/* control word (16bits) */
	uint16_t	s87_sw __aligned(4);	/* status word (16bits) */
	uint16_t	s87_tw __aligned(4);	/* tag word (16bits) */
	union fp_addr	s87_ip;		/* floating point instruction pointer */
#define s87_opcode s87_ip.fa_32.fa_opcode	/* opcode last executed (11bits) */
	union fp_addr	s87_dp;		/* floating operand offset */
	struct fpacc87	s87_ac[8];	/* accumulator contents, 0-7 */
};
__CTASSERT_NOLINT(sizeof (struct save87) == 108);

/* FPU/MMX/SSE/SSE2 context */
struct fxsave {
/*0*/	uint16_t	fx_cw;		/* FPU Control Word */
	uint16_t	fx_sw;		/* FPU Status Word */
	uint8_t		fx_tw;		/* FPU Tag Word (abridged) */
	uint16_t	fx_opcode;	/* FPU Opcode */
	union fp_addr	fx_ip;		/* FPU Instruction Pointer */
/*16*/	union fp_addr	fx_dp;		/* FPU Data pointer */
	uint32_t	fx_mxcsr;	/* MXCSR Register State */
	uint32_t	fx_mxcsr_mask;
	struct fpaccfx	fx_87_ac[8];	/* 8 x87 registers */
	struct xmmreg	fx_xmm[16];	/* XMM regs (8 in 32bit modes) */
	uint8_t		fx_rsvd[48];
	uint8_t		fx_kernel[48];	/* Not written by the hardware */
} __aligned(16);
__CTASSERT_NOLINT(sizeof (struct fxsave) == 512);

/* The end of the fsave buffer can be used by the operating system */
struct fxsave_os {
	uint8_t		fxo_fxsave[512 - 48];
	/* 48 bytes available, NB copied to/from userspace */
	uint16_t	fxo_dflt_cw;	/* Control word for signal handlers */
};

/*
 * For XSAVE a 64byte header follows the fxsave data.
 * Currently it only contains one field of which only 3 bits are defined.
 * Some other parts must be zero - zero it all.
 *
 * The xsh_xstate_bv bits match those of XCR0:
 *   XCR0_X87        0x00000001      x87 FPU/MMX state
 *   XCR0_SSE        0x00000002      SSE state
 *   XCR0_AVX        0x00000004      AVX state (ymmn registers)
 *
 * The offsets and sizes of any save areas can be found by reading
 * the correct control registers.
 */

struct xsave_header {
	uint64_t	xsh_fxsave[64];	/* to align in the union */
	uint64_t	xsh_xstate_bv;	/* bitmap of saved sub structures */
	uint64_t	xsh_rsrvd[2];	/* must be zero */
	uint64_t	xsh_reserved[5];/* best if zero */
};
__CTASSERT(sizeof (struct xsave_header) == 512 + 64);

/*
 * The ymm save area actually follows the xsave_header.
 */
struct xsave_ymm {
	struct ymmreg	xs_ymm[16];	/* High bits of YMM registers */
};
__CTASSERT(sizeof (struct xsave_ymm) == 256);

/*
 * The following union is placed at the end of the pcb.
 * It is defined this way to separate the definitions and to
 * minimise the number of union/struct selectors.
 * NB: Some userspace stuff (eg firefox) uses it to parse ucontext.
 */
union savefpu {
	struct save87		sv_87;
	struct fxsave		sv_xmm;
#ifdef _KERNEL
	struct fxsave_os	sv_os;
	struct xsave_header	sv_xsave_hdr;
#endif
};

/*
 * 80387 control and status word bits
 *
 * The only reference I can find to bits 0x40 and 0x80 in the control word
 * is for the Weitek 1167/3167.
 * I (dsl) can't find why the default word has 0x40 set.
 *
 * A stack error is signalled as an INVOP that also sets STACK_FAULT
 * (other INVOP do not clear STACK_FAULT).
 */
/* Interrupt masks (set masks interrupt) and status bits */
#define EN_SW_INVOP		0x0001  /* Invalid operation */
#define EN_SW_DENORM		0x0002  /* Denormalized operand */
#define EN_SW_ZERODIV		0x0004  /* Divide by zero */
#define EN_SW_OVERFLOW		0x0008  /* Overflow */
#define EN_SW_UNDERFLOW		0x0010  /* Underflow */
#define EN_SW_PRECLOSS		0x0020  /* Loss of precision */
/* Status word bits (reserved in control word) */
#define EN_SW_STACK_FAULT	0x0040	/* Stack under/overflow */
#define EN_SW_ERROR_SUMMARY	0x0080	/* Unmasked error has ocurred */
/* Control bits (badly named) */
#define EN_SW_CTL_PREC		0x0300	/* Precision control */
#define EN_SW_PREC_24		0x0000	/* Single precision */
#define EN_SW_PREC_53		0x0200	/* Double precision */
#define EN_SW_PREC_64		0x0300	/* Extended precision */
#define EN_SW_CTL_ROUND		0x0c00	/* Rounding control */
#define EN_SW_ROUND_EVEN	0x0000	/* Round to nearest even */
#define EN_SW_ROUND_DOWN	0x0400	/* Round towards minus infinity */
#define EN_SW_ROUND_UP		0x0800	/* Round towards plus infinity */
#define EN_SW_ROUND_ZERO	0x0c00	/* Round towards zero (truncates) */
#define EN_SW_CTL_INF		0x1000	/* Infinity control, not used  */

/*
 * The standard 0x87 control word from finit is 0x37F, giving:
 *	round to nearest
 *	64-bit precision
 *	all exceptions masked.
 *
 * NetBSD used to select:
 *	round to nearest
 *	53-bit precision
 *	all exceptions masked.
 * Stating: 64-bit precision often gives bad results with high level
 * languages because it makes the results of calculations depend on whether
 * intermediate values are stored in memory or in FPU registers.
 * Also some 'pathological divisions' give an error in the LSB because
 * the value is first rounded up when the 64bit mantissa is generated,
 * and then again when it is truncated to 53 bits.
 *
 * However the C language explicitly allows the extra precision.
 *
 * The iBCS control word has underflow, overflow, zero divide, and invalid
 * operation exceptions unmasked.  But that causes an unexpected exception
 * in the test program 'paranoia' and makes denormals useless (DBL_MIN / 2
 * underflows).  It doesn't make a lot of sense to trap underflow without
 * trapping denormals.
 */
#define	__INITIAL_NPXCW__	0x037f
/* Modern NetBSD uses the default control word.. */
#define	__NetBSD_NPXCW__	__INITIAL_NPXCW__
/* NetBSD before 6.99.26 forced IEEE double precision. */
#define	__NetBSD_COMPAT_NPXCW__	0x127f
/* FreeBSD leaves some exceptions unmasked as well. */
#define	__FreeBSD_NPXCW__	0x1272
/* iBCS2 goes a bit further and leaves the underflow exception unmasked. */
#define	__iBCS2_NPXCW__		0x0262
/* Linux just uses the default control word. */
#define	__Linux_NPXCW__		__INITIAL_NPXCW__
/* SVR4 uses the same control word as iBCS2. */
#define	__SVR4_NPXCW__		0x0262

/*
 * The default MXCSR value at reset is 0x1f80, IA-32 Instruction
 * Set Reference, pg. 3-369.
 *
 * The low 6 bits of the mxcsr are the fp status bits (same order as x87).
 * Bit 6 is 'denormals are zero' (speeds up calculations).
 * Bits 7-16 are the interrupt mask bits (same order, 1 to mask).
 * Bits 13 and 14 are rounding control.
 * Bit 15 is 'flush to zero' - affects underflow.
 * Bits 16-31 must be zero.
 */
#define	__INITIAL_MXCSR__	0x1f80
#define	__INITIAL_MXCSR_MASK__	0xffbf

#endif /* _X86_CPU_EXTENDED_STATE_H_ */