View | Details | Raw Unified | Return to bug 28070
Collapse All | Expand All

(-)sys/conf/options.i386 (+1 lines)
Lines 53-70 Link Here
53
CPU_LOOP_EN			opt_cpu.h
53
CPU_LOOP_EN			opt_cpu.h
54
CPU_PPRO2CELERON		opt_cpu.h
54
CPU_PPRO2CELERON		opt_cpu.h
55
CPU_RSTK_EN			opt_cpu.h
55
CPU_RSTK_EN			opt_cpu.h
56
CPU_SUSP_HLT			opt_cpu.h
56
CPU_SUSP_HLT			opt_cpu.h
57
CPU_UPGRADE_HW_CACHE		opt_cpu.h
57
CPU_UPGRADE_HW_CACHE		opt_cpu.h
58
CPU_WT_ALLOC			opt_cpu.h
58
CPU_WT_ALLOC			opt_cpu.h
59
CYRIX_CACHE_WORKS		opt_cpu.h
59
CYRIX_CACHE_WORKS		opt_cpu.h
60
CYRIX_CACHE_REALLY_WORKS	opt_cpu.h
60
CYRIX_CACHE_REALLY_WORKS	opt_cpu.h
61
NO_MEMORY_HOLE			opt_cpu.h
61
NO_MEMORY_HOLE			opt_cpu.h
62
CPU_ENABLE_SSE			opt_cpu.h
62
63
63
# The CPU type affects the endian conversion functions all over the kernel.
64
# The CPU type affects the endian conversion functions all over the kernel.
64
I386_CPU		opt_global.h
65
I386_CPU		opt_global.h
65
I486_CPU		opt_global.h
66
I486_CPU		opt_global.h
66
I586_CPU		opt_global.h
67
I586_CPU		opt_global.h
67
I686_CPU		opt_global.h
68
I686_CPU		opt_global.h
68
69
69
MAXCONS			opt_syscons.h
70
MAXCONS			opt_syscons.h
70
SC_ALT_MOUSE_IMAGE	opt_syscons.h
71
SC_ALT_MOUSE_IMAGE	opt_syscons.h
(-)sys/i386/conf/NOTES (+2 lines)
Lines 181-198 Link Here
181
#
181
#
182
# CPU_CYRIX_NO_LOCK enables weak locking for the entire address space
182
# CPU_CYRIX_NO_LOCK enables weak locking for the entire address space
183
# of Cyrix 6x86 and 6x86MX CPUs by setting the NO_LOCK bit of CCR1.
183
# of Cyrix 6x86 and 6x86MX CPUs by setting the NO_LOCK bit of CCR1.
184
# Otherwise, the NO_LOCK bit of CCR1 is cleared.  (NOTE 3)
184
# Otherwise, the NO_LOCK bit of CCR1 is cleared.  (NOTE 3)
185
#
185
#
186
# CPU_DISABLE_5X86_LSSER disables load store serialize (i.e. enables
186
# CPU_DISABLE_5X86_LSSER disables load store serialize (i.e. enables
187
# reorder).  This option should not be used if you use memory mapped
187
# reorder).  This option should not be used if you use memory mapped
188
# I/O device(s).
188
# I/O device(s).
189
#
189
#
190
# CPU_ENABLE_SSE enables SSE/MMX2 instructions support.
191
#
190
# CPU_FASTER_5X86_FPU enables faster FPU exception handler.
192
# CPU_FASTER_5X86_FPU enables faster FPU exception handler.
191
#
193
#
192
# CPU_I486_ON_386 enables CPU cache on i486 based CPU upgrade products
194
# CPU_I486_ON_386 enables CPU cache on i486 based CPU upgrade products
193
# for i386 machines.
195
# for i386 machines.
194
#
196
#
195
# CPU_IORT defines I/O clock delay time (NOTE 1).  Default values of
197
# CPU_IORT defines I/O clock delay time (NOTE 1).  Default values of
196
# I/O clock delay time on Cyrix 5x86 and 6x86 are 0 and 7,respectively
198
# I/O clock delay time on Cyrix 5x86 and 6x86 are 0 and 7,respectively
197
# (no clock delay).
199
# (no clock delay).
198
#
200
#
(-)sys/i386/i386/genassym.c (-2 / +3 lines)
Lines 120-139 Link Here
120
ASSYM(PCB_DR2, offsetof(struct pcb, pcb_dr2));
120
ASSYM(PCB_DR2, offsetof(struct pcb, pcb_dr2));
121
ASSYM(PCB_DR3, offsetof(struct pcb, pcb_dr3));
121
ASSYM(PCB_DR3, offsetof(struct pcb, pcb_dr3));
122
ASSYM(PCB_DR6, offsetof(struct pcb, pcb_dr6));
122
ASSYM(PCB_DR6, offsetof(struct pcb, pcb_dr6));
123
ASSYM(PCB_DR7, offsetof(struct pcb, pcb_dr7));
123
ASSYM(PCB_DR7, offsetof(struct pcb, pcb_dr7));
124
ASSYM(PCB_DBREGS, PCB_DBREGS);
124
ASSYM(PCB_DBREGS, PCB_DBREGS);
125
ASSYM(PCB_EXT, offsetof(struct pcb, pcb_ext));
125
ASSYM(PCB_EXT, offsetof(struct pcb, pcb_ext));
126
126
127
ASSYM(PCB_SPARE, offsetof(struct pcb, __pcb_spare));
127
ASSYM(PCB_SPARE, offsetof(struct pcb, __pcb_spare));
128
ASSYM(PCB_FLAGS, offsetof(struct pcb, pcb_flags));
128
ASSYM(PCB_FLAGS, offsetof(struct pcb, pcb_flags));
129
ASSYM(PCB_SAVEFPU, offsetof(struct pcb, pcb_savefpu));
129
ASSYM(PCB_SAVEFPU, offsetof(struct pcb, pcb_save));
130
ASSYM(PCB_SAVEFPU_SIZE, sizeof(struct save87));
130
ASSYM(PCB_SAVEFPU_SIZE, sizeof(union savefpu));
131
ASSYM(PCB_SAVE87_SIZE, sizeof(struct save87));
131
ASSYM(PCB_ONFAULT, offsetof(struct pcb, pcb_onfault));
132
ASSYM(PCB_ONFAULT, offsetof(struct pcb, pcb_onfault));
132
133
133
#ifdef SMP
134
#ifdef SMP
134
ASSYM(PCB_SIZE, sizeof(struct pcb));
135
ASSYM(PCB_SIZE, sizeof(struct pcb));
135
#endif
136
#endif
136
137
137
ASSYM(TF_TRAPNO, offsetof(struct trapframe, tf_trapno));
138
ASSYM(TF_TRAPNO, offsetof(struct trapframe, tf_trapno));
138
ASSYM(TF_ERR, offsetof(struct trapframe, tf_err));
139
ASSYM(TF_ERR, offsetof(struct trapframe, tf_err));
139
ASSYM(TF_CS, offsetof(struct trapframe, tf_cs));
140
ASSYM(TF_CS, offsetof(struct trapframe, tf_cs));
(-)sys/i386/i386/initcpu.c (-1 / +22 lines)
Lines 28-45 Link Here
28
 *
28
 *
29
 * $FreeBSD: src/sys/i386/i386/initcpu.c,v 1.25 2001/03/28 03:06:06 jhb Exp $
29
 * $FreeBSD: src/sys/i386/i386/initcpu.c,v 1.25 2001/03/28 03:06:06 jhb Exp $
30
 */
30
 */
31
31
32
#include "opt_cpu.h"
32
#include "opt_cpu.h"
33
33
34
#include <sys/param.h>
34
#include <sys/param.h>
35
#include <sys/kernel.h>
35
#include <sys/kernel.h>
36
#include <sys/systm.h>
36
#include <sys/systm.h>
37
#include <sys/sysctl.h>
37
38
38
#include <machine/cputypes.h>
39
#include <machine/cputypes.h>
39
#include <machine/md_var.h>
40
#include <machine/md_var.h>
40
#include <machine/specialreg.h>
41
#include <machine/specialreg.h>
41
42
42
void initializecpu(void);
43
void initializecpu(void);
43
#if defined(I586_CPU) && defined(CPU_WT_ALLOC)
44
#if defined(I586_CPU) && defined(CPU_WT_ALLOC)
44
void	enable_K5_wt_alloc(void);
45
void	enable_K5_wt_alloc(void);
45
void	enable_K6_wt_alloc(void);
46
void	enable_K6_wt_alloc(void);
Lines 55-73 Link Here
55
static void init_i486_on_386(void);
56
static void init_i486_on_386(void);
56
#endif
57
#endif
57
static void init_6x86(void);
58
static void init_6x86(void);
58
#endif /* I486_CPU */
59
#endif /* I486_CPU */
59
60
60
#ifdef I686_CPU
61
#ifdef I686_CPU
61
static void	init_6x86MX(void);
62
static void	init_6x86MX(void);
62
static void	init_ppro(void);
63
static void	init_ppro(void);
63
static void	init_mendocino(void);
64
static void	init_mendocino(void);
65
#if defined(CPU_ENABLE_SSE)
66
void	init_sse(void);
64
#endif
67
#endif
68
#endif /* I686_CPU */
69
70
int	hw_instruction_sse = 0;
71
SYSCTL_INT(_hw, OID_AUTO, instruction_sse, CTLFLAG_RD,
72
	&hw_instruction_sse, 0,
73
	"SSE/MMX2 instructions available in CPU");
65
74
66
#ifdef I486_CPU
75
#ifdef I486_CPU
67
/*
76
/*
68
 * IBM Blue Lightning
77
 * IBM Blue Lightning
69
 */
78
 */
70
static void
79
static void
71
init_bluelightning(void)
80
init_bluelightning(void)
72
{
81
{
73
	u_long	eflags;
82
	u_long	eflags;
Lines 494-512 Link Here
494
		bbl_cr_ctl3 |= 5 << 1;
503
		bbl_cr_ctl3 |= 5 << 1;
495
#endif
504
#endif
496
		wrmsr(0x11e, bbl_cr_ctl3);
505
		wrmsr(0x11e, bbl_cr_ctl3);
497
	}
506
	}
498
507
499
	load_cr0(rcr0() & ~(CR0_CD | CR0_NW));
508
	load_cr0(rcr0() & ~(CR0_CD | CR0_NW));
500
	write_eflags(eflags);
509
	write_eflags(eflags);
501
#endif /* CPU_PPRO2CELERON */
510
#endif /* CPU_PPRO2CELERON */
502
}
511
}
503
	
512
#if defined(CPU_ENABLE_SSE)
513
void
514
init_sse(void)
515
{
516
	if ((cpu_feature & CPUID_XMM) && (cpu_feature & CPUID_FXSR)) {
517
		load_cr4(rcr4() | CR4_FXSR | CR4_XMM);
518
		cpu_fxsr = hw_instruction_sse = 1;
519
	}
520
}
521
#endif
504
#endif /* I686_CPU */
522
#endif /* I686_CPU */
505
523
506
void
524
void
507
initializecpu(void)
525
initializecpu(void)
508
{
526
{
509
527
510
	switch (cpu) {
528
	switch (cpu) {
511
#ifdef I486_CPU
529
#ifdef I486_CPU
512
	case CPU_BLUE:
530
	case CPU_BLUE:
Lines 538-555 Link Here
538
		if (strcmp(cpu_vendor, "GenuineIntel") == 0) {
556
		if (strcmp(cpu_vendor, "GenuineIntel") == 0) {
539
			switch (cpu_id & 0xff0) {
557
			switch (cpu_id & 0xff0) {
540
			case 0x610:
558
			case 0x610:
541
				init_ppro();
559
				init_ppro();
542
				break;
560
				break;
543
			case 0x660:
561
			case 0x660:
544
				init_mendocino();
562
				init_mendocino();
545
				break;
563
				break;
546
			}
564
			}
565
#if defined(CPU_ENABLE_SSE)
566
			init_sse();
567
#endif
547
		}
568
		}
548
		break;
569
		break;
549
#endif
570
#endif
550
	default:
571
	default:
551
		break;
572
		break;
552
	}
573
	}
553
574
554
#if defined(PC98) && !defined(CPU_UPGRADE_HW_CACHE)
575
#if defined(PC98) && !defined(CPU_UPGRADE_HW_CACHE)
555
	/*
576
	/*
(-)sys/i386/i386/locore.s (-1 / +2 lines)
Lines 107-130 Link Here
107
	ALIGN_DATA		/* just to be sure */
107
	ALIGN_DATA		/* just to be sure */
108
108
109
	.globl	HIDENAME(tmpstk)
109
	.globl	HIDENAME(tmpstk)
110
	.space	0x2000		/* space for tmpstk - temporary stack */
110
	.space	0x2000		/* space for tmpstk - temporary stack */
111
HIDENAME(tmpstk):
111
HIDENAME(tmpstk):
112
112
113
	.globl	boothowto,bootdev
113
	.globl	boothowto,bootdev
114
114
115
	.globl	cpu,cpu_vendor,cpu_id,bootinfo
115
	.globl	cpu,cpu_vendor,cpu_id,bootinfo
116
	.globl	cpu_high, cpu_feature
116
	.globl	cpu_high, cpu_feature, cpu_fxsr
117
117
118
cpu:		.long	0			/* are we 386, 386sx, or 486 */
118
cpu:		.long	0			/* are we 386, 386sx, or 486 */
119
cpu_id:		.long	0			/* stepping ID */
119
cpu_id:		.long	0			/* stepping ID */
120
cpu_high:	.long	0			/* highest arg to CPUID */
120
cpu_high:	.long	0			/* highest arg to CPUID */
121
cpu_feature:	.long	0			/* features */
121
cpu_feature:	.long	0			/* features */
122
cpu_fxsr:	.long	0			/* use fxsave/fxrstor instruction */
122
cpu_vendor:	.space	20			/* CPU origin code */
123
cpu_vendor:	.space	20			/* CPU origin code */
123
bootinfo:	.space	BOOTINFO_SIZE		/* bootinfo that we can handle */
124
bootinfo:	.space	BOOTINFO_SIZE		/* bootinfo that we can handle */
124
125
125
KERNend:	.long	0			/* phys addr end of kernel (just after bss) */
126
KERNend:	.long	0			/* phys addr end of kernel (just after bss) */
126
physfree:	.long	0			/* phys addr of next free page */
127
physfree:	.long	0			/* phys addr of next free page */
127
128
128
#ifdef SMP
129
#ifdef SMP
129
		.globl	cpu0prvpage
130
		.globl	cpu0prvpage
130
cpu0pp:		.long	0			/* phys addr cpu0 private pg */
131
cpu0pp:		.long	0			/* phys addr cpu0 private pg */
(-)sys/i386/i386/machdep.c (-4 / +76 lines)
Lines 125-142 Link Here
125
extern void earlysetcpuclass(void);	/* same header file */
125
extern void earlysetcpuclass(void);	/* same header file */
126
extern void finishidentcpu(void);
126
extern void finishidentcpu(void);
127
extern void panicifcpuunsupported(void);
127
extern void panicifcpuunsupported(void);
128
extern void initializecpu(void);
128
extern void initializecpu(void);
129
129
130
#define	CS_SECURE(cs)		(ISPL(cs) == SEL_UPL)
130
#define	CS_SECURE(cs)		(ISPL(cs) == SEL_UPL)
131
#define	EFL_SECURE(ef, oef)	((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0)
131
#define	EFL_SECURE(ef, oef)	((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0)
132
132
133
static void cpu_startup __P((void *));
133
static void cpu_startup __P((void *));
134
#ifdef CPU_ENABLE_SSE
135
static void set_fpregs_xmm __P((struct save87 *, struct savexmm *));
136
static void fill_fpregs_xmm __P((struct savexmm *, struct save87 *));
137
#endif /* CPU_ENABLE_SSE */
134
SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL)
138
SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL)
135
139
136
int	_udatasel, _ucodesel;
140
int	_udatasel, _ucodesel;
137
u_int	atdevbase;
141
u_int	atdevbase;
138
142
139
#if defined(SWTCH_OPTIM_STATS)
143
#if defined(SWTCH_OPTIM_STATS)
140
extern int swtch_optim_stats;
144
extern int swtch_optim_stats;
141
SYSCTL_INT(_debug, OID_AUTO, swtch_optim_stats,
145
SYSCTL_INT(_debug, OID_AUTO, swtch_optim_stats,
142
	CTLFLAG_RD, &swtch_optim_stats, 0, "");
146
	CTLFLAG_RD, &swtch_optim_stats, 0, "");
Lines 2143-2162 Link Here
2143
		tp = p->p_md.md_regs;
2147
		tp = p->p_md.md_regs;
2144
		frame_copy = *tp;
2148
		frame_copy = *tp;
2145
		*(int *)((char *)&frame_copy + (off - min)) = data;
2149
		*(int *)((char *)&frame_copy + (off - min)) = data;
2146
		if (!EFL_SECURE(frame_copy.tf_eflags, tp->tf_eflags) ||
2150
		if (!EFL_SECURE(frame_copy.tf_eflags, tp->tf_eflags) ||
2147
		    !CS_SECURE(frame_copy.tf_cs))
2151
		    !CS_SECURE(frame_copy.tf_cs))
2148
			return (EINVAL);
2152
			return (EINVAL);
2149
		*(int*)((char *)p->p_addr + off) = data;
2153
		*(int*)((char *)p->p_addr + off) = data;
2150
		return (0);
2154
		return (0);
2151
	}
2155
	}
2152
	min = offsetof(struct user, u_pcb) + offsetof(struct pcb, pcb_savefpu);
2156
	min = offsetof(struct user, u_pcb) + offsetof(struct pcb, pcb_save);
2153
	if (off >= min && off <= min + sizeof(struct save87) - sizeof(int)) {
2157
	if (off >= min && off <= min + sizeof(union savefpu) - sizeof(int)) {
2154
		*(int*)((char *)p->p_addr + off) = data;
2158
		*(int*)((char *)p->p_addr + off) = data;
2155
		return (0);
2159
		return (0);
2156
	}
2160
	}
2157
	return (EFAULT);
2161
	return (EFAULT);
2158
}
2162
}
2159
2163
2160
int
2164
int
2161
fill_regs(p, regs)
2165
fill_regs(p, regs)
2162
	struct proc *p;
2166
	struct proc *p;
Lines 2212-2244 Link Here
2212
	tp->tf_cs = regs->r_cs;
2216
	tp->tf_cs = regs->r_cs;
2213
	tp->tf_eflags = regs->r_eflags;
2217
	tp->tf_eflags = regs->r_eflags;
2214
	tp->tf_esp = regs->r_esp;
2218
	tp->tf_esp = regs->r_esp;
2215
	tp->tf_ss = regs->r_ss;
2219
	tp->tf_ss = regs->r_ss;
2216
	pcb = &p->p_addr->u_pcb;
2220
	pcb = &p->p_addr->u_pcb;
2217
	pcb->pcb_gs = regs->r_gs;
2221
	pcb->pcb_gs = regs->r_gs;
2218
	return (0);
2222
	return (0);
2219
}
2223
}
2220
2224
2225
#ifdef CPU_ENABLE_SSE
2226
static void
2227
fill_fpregs_xmm(sv_xmm, sv_87)
2228
	struct savexmm *sv_xmm;
2229
	struct save87 *sv_87;
2230
{
2231
	register struct env87 *penv_87 = &sv_87->sv_env;
2232
	register struct envxmm *penv_xmm = &sv_xmm->sv_env;
2233
	int i;
2234
2235
	/* FPU control/status */
2236
	penv_87->en_cw = penv_xmm->en_cw;
2237
	penv_87->en_sw = penv_xmm->en_sw;
2238
	penv_87->en_tw = penv_xmm->en_tw;
2239
	penv_87->en_fip = penv_xmm->en_fip;
2240
	penv_87->en_fcs = penv_xmm->en_fcs;
2241
	penv_87->en_opcode = penv_xmm->en_opcode;
2242
	penv_87->en_foo = penv_xmm->en_foo;
2243
	penv_87->en_fos = penv_xmm->en_fos;
2244
2245
	/* FPU registers */
2246
	for (i = 0; i < 8; ++i)
2247
		sv_87->sv_ac[i] = sv_xmm->sv_fp[i].fp_acc;
2248
2249
	sv_87->sv_ex_sw = sv_xmm->sv_ex_sw;
2250
}
2251
2252
static void
2253
set_fpregs_xmm(sv_87, sv_xmm)
2254
	struct save87 *sv_87;
2255
	struct savexmm *sv_xmm;
2256
{
2257
	register struct env87 *penv_87 = &sv_87->sv_env;
2258
	register struct envxmm *penv_xmm = &sv_xmm->sv_env;
2259
	int i;
2260
2261
/* FPU control/status */
2262
	penv_xmm->en_cw = penv_87->en_cw;
2263
	penv_xmm->en_sw = penv_87->en_sw;
2264
	penv_xmm->en_tw = penv_87->en_tw;
2265
	penv_xmm->en_fip = penv_87->en_fip;
2266
	penv_xmm->en_fcs = penv_87->en_fcs;
2267
	penv_xmm->en_opcode = penv_87->en_opcode;
2268
	penv_xmm->en_foo = penv_87->en_foo;
2269
	penv_xmm->en_fos = penv_87->en_fos;
2270
2271
	/* FPU registers */
2272
	for (i = 0; i < 8; ++i)
2273
		sv_xmm->sv_fp[i].fp_acc = sv_87->sv_ac[i];
2274
2275
	sv_xmm->sv_ex_sw = sv_87->sv_ex_sw;
2276
}
2277
#endif /* CPU_ENABLE_SSE */
2278
2221
int
2279
int
2222
fill_fpregs(p, fpregs)
2280
fill_fpregs(p, fpregs)
2223
	struct proc *p;
2281
	struct proc *p;
2224
	struct fpreg *fpregs;
2282
	struct fpreg *fpregs;
2225
{
2283
{
2226
	bcopy(&p->p_addr->u_pcb.pcb_savefpu, fpregs, sizeof *fpregs);
2284
#ifdef CPU_ENABLE_SSE
2285
	if (cpu_fxsr) {
2286
		fill_fpregs_xmm(&p->p_addr->u_pcb.pcb_save.sv_xmm,
2287
						(struct save87 *)fpregs);
2288
		return (0);
2289
	}
2290
#endif /* CPU_ENABLE_SSE */
2291
	bcopy(&p->p_addr->u_pcb.pcb_save.sv_87, fpregs, sizeof *fpregs);
2227
	return (0);
2292
	return (0);
2228
}
2293
}
2229
2294
2230
int
2295
int
2231
set_fpregs(p, fpregs)
2296
set_fpregs(p, fpregs)
2232
	struct proc *p;
2297
	struct proc *p;
2233
	struct fpreg *fpregs;
2298
	struct fpreg *fpregs;
2234
{
2299
{
2235
	bcopy(fpregs, &p->p_addr->u_pcb.pcb_savefpu, sizeof *fpregs);
2300
#ifdef CPU_ENABLE_SSE
2301
	if (cpu_fxsr) {
2302
		set_fpregs_xmm((struct save87 *)fpregs,
2303
					&p->p_addr->u_pcb.pcb_save.sv_xmm);
2304
		return (0);
2305
	}
2306
#endif /* CPU_ENABLE_SSE */
2307
	bcopy(fpregs, &p->p_addr->u_pcb.pcb_save.sv_87, sizeof *fpregs);
2236
	return (0);
2308
	return (0);
2237
}
2309
}
2238
2310
2239
int
2311
int
2240
fill_dbregs(p, dbregs)
2312
fill_dbregs(p, dbregs)
2241
	struct proc *p;
2313
	struct proc *p;
2242
	struct dbreg *dbregs;
2314
	struct dbreg *dbregs;
2243
{
2315
{
2244
	struct pcb *pcb;
2316
	struct pcb *pcb;
(-)sys/i386/i386/mp_machdep.c (+9 lines)
Lines 227-244 Link Here
227
#define MP_ENABLE_POST		0x14
227
#define MP_ENABLE_POST		0x14
228
#define MPTABLE_PASS2_POST	0x15
228
#define MPTABLE_PASS2_POST	0x15
229
229
230
#define START_ALL_APS_POST	0x16
230
#define START_ALL_APS_POST	0x16
231
#define INSTALL_AP_TRAMP_POST	0x17
231
#define INSTALL_AP_TRAMP_POST	0x17
232
#define START_AP_POST		0x18
232
#define START_AP_POST		0x18
233
233
234
#define MP_ANNOUNCE_POST	0x19
234
#define MP_ANNOUNCE_POST	0x19
235
235
236
#if defined(CPU_ENABLE_SSE)
237
extern void	init_sse(void);
238
#endif
239
236
/* used to hold the AP's until we are ready to release them */
240
/* used to hold the AP's until we are ready to release them */
237
static struct mtx ap_boot_mtx;
241
static struct mtx ap_boot_mtx;
238
242
239
/** XXX FIXME: where does this really belong, isa.h/isa.c perhaps? */
243
/** XXX FIXME: where does this really belong, isa.h/isa.c perhaps? */
240
int	current_postcode;
244
int	current_postcode;
241
245
242
/** XXX FIXME: what system files declare these??? */
246
/** XXX FIXME: what system files declare these??? */
243
extern struct region_descriptor r_gdt, r_idt;
247
extern struct region_descriptor r_gdt, r_idt;
244
248
Lines 2258-2275 Link Here
2258
	PCPU_SET(other_cpus, all_cpus & ~(1 << PCPU_GET(cpuid)));
2262
	PCPU_SET(other_cpus, all_cpus & ~(1 << PCPU_GET(cpuid)));
2259
2263
2260
	printf("SMP: AP CPU #%d Launched!\n", PCPU_GET(cpuid));
2264
	printf("SMP: AP CPU #%d Launched!\n", PCPU_GET(cpuid));
2261
2265
2262
	/* set up CPU registers and state */
2266
	/* set up CPU registers and state */
2263
	cpu_setregs();
2267
	cpu_setregs();
2264
2268
2265
	/* set up FPU state on the AP */
2269
	/* set up FPU state on the AP */
2266
	npxinit(__INITIAL_NPXCW__);
2270
	npxinit(__INITIAL_NPXCW__);
2271
2272
	/* Setup the SSE */
2273
#if defined(CPU_ENABLE_SSE)
2274
	init_sse();
2275
#endif
2267
2276
2268
	/* A quick check from sanity claus */
2277
	/* A quick check from sanity claus */
2269
	apic_id = (apic_id_to_logical[(lapic.id & 0x0f000000) >> 24]);
2278
	apic_id = (apic_id_to_logical[(lapic.id & 0x0f000000) >> 24]);
2270
	if (PCPU_GET(cpuid) != apic_id) {
2279
	if (PCPU_GET(cpuid) != apic_id) {
2271
		printf("SMP: cpuid = %d\n", PCPU_GET(cpuid));
2280
		printf("SMP: cpuid = %d\n", PCPU_GET(cpuid));
2272
		printf("SMP: apic_id = %d\n", apic_id);
2281
		printf("SMP: apic_id = %d\n", apic_id);
2273
		printf("PTD[MPPTDI] = %p\n", (void *)PTD[MPPTDI]);
2282
		printf("PTD[MPPTDI] = %p\n", (void *)PTD[MPPTDI]);
2274
		panic("cpuid mismatch! boom!!");
2283
		panic("cpuid mismatch! boom!!");
2275
	}
2284
	}
(-)sys/i386/i386/support.s (-4 / +4 lines)
Lines 970-988 Link Here
970
	src in %esi
970
	src in %esi
971
	dst in %edi
971
	dst in %edi
972
	len in %ecx		XXX changed to on stack for profiling
972
	len in %ecx		XXX changed to on stack for profiling
973
	uses %eax and %edx for tmp. storage
973
	uses %eax and %edx for tmp. storage
974
 */
974
 */
975
/* XXX use ENTRY() to get profiling.  fastmove() is actually a non-entry. */
975
/* XXX use ENTRY() to get profiling.  fastmove() is actually a non-entry. */
976
ENTRY(fastmove)
976
ENTRY(fastmove)
977
	pushl	%ebp
977
	pushl	%ebp
978
	movl	%esp,%ebp
978
	movl	%esp,%ebp
979
	subl	$PCB_SAVEFPU_SIZE+3*4,%esp
979
	subl	$PCB_SAVE87_SIZE+3*4,%esp
980
980
981
	movl	8(%ebp),%ecx
981
	movl	8(%ebp),%ecx
982
	cmpl	$63,%ecx
982
	cmpl	$63,%ecx
983
	jbe	fastmove_tail
983
	jbe	fastmove_tail
984
984
985
	testl	$7,%esi	/* check if src addr is multiple of 8 */
985
	testl	$7,%esi	/* check if src addr is multiple of 8 */
986
	jnz	fastmove_tail
986
	jnz	fastmove_tail
987
987
988
	testl	$7,%edi	/* check if dst addr is multiple of 8 */
988
	testl	$7,%edi	/* check if dst addr is multiple of 8 */
Lines 1012-1030 Link Here
1012
 */
1012
 */
1013
/* tmp = curpcb->pcb_savefpu; */
1013
/* tmp = curpcb->pcb_savefpu; */
1014
	movl	%ecx,-12(%ebp)
1014
	movl	%ecx,-12(%ebp)
1015
	movl	%esi,-8(%ebp)
1015
	movl	%esi,-8(%ebp)
1016
	movl	%edi,-4(%ebp)
1016
	movl	%edi,-4(%ebp)
1017
	movl	%esp,%edi
1017
	movl	%esp,%edi
1018
	movl	PCPU(CURPCB),%esi
1018
	movl	PCPU(CURPCB),%esi
1019
	addl	$PCB_SAVEFPU,%esi
1019
	addl	$PCB_SAVEFPU,%esi
1020
	cld
1020
	cld
1021
	movl	$PCB_SAVEFPU_SIZE>>2,%ecx
1021
	movl	$PCB_SAVE87_SIZE>>2,%ecx
1022
	rep
1022
	rep
1023
	movsl
1023
	movsl
1024
	movl	-12(%ebp),%ecx
1024
	movl	-12(%ebp),%ecx
1025
	movl	-8(%ebp),%esi
1025
	movl	-8(%ebp),%esi
1026
	movl	-4(%ebp),%edi
1026
	movl	-4(%ebp),%edi
1027
/* stop_emulating(); */
1027
/* stop_emulating(); */
1028
	clts
1028
	clts
1029
/* npxproc = curproc; */
1029
/* npxproc = curproc; */
1030
	movl	PCPU(CURPROC),%eax
1030
	movl	PCPU(CURPROC),%eax
Lines 1096-1114 Link Here
1096
1096
1097
/* curpcb->pcb_savefpu = tmp; */
1097
/* curpcb->pcb_savefpu = tmp; */
1098
	movl	%ecx,-12(%ebp)
1098
	movl	%ecx,-12(%ebp)
1099
	movl	%esi,-8(%ebp)
1099
	movl	%esi,-8(%ebp)
1100
	movl	%edi,-4(%ebp)
1100
	movl	%edi,-4(%ebp)
1101
	movl	PCPU(CURPCB),%edi
1101
	movl	PCPU(CURPCB),%edi
1102
	addl	$PCB_SAVEFPU,%edi
1102
	addl	$PCB_SAVEFPU,%edi
1103
	movl	%esp,%esi
1103
	movl	%esp,%esi
1104
	cld
1104
	cld
1105
	movl	$PCB_SAVEFPU_SIZE>>2,%ecx
1105
	movl	$PCB_SAVE87_SIZE>>2,%ecx
1106
	rep
1106
	rep
1107
	movsl
1107
	movsl
1108
	movl	-12(%ebp),%ecx
1108
	movl	-12(%ebp),%ecx
1109
	movl	-8(%ebp),%esi
1109
	movl	-8(%ebp),%esi
1110
	movl	-4(%ebp),%edi
1110
	movl	-4(%ebp),%edi
1111
1111
1112
/* start_emulating(); */
1112
/* start_emulating(); */
1113
	smsw	%ax
1113
	smsw	%ax
1114
	orb	$CR0_TS,%al
1114
	orb	$CR0_TS,%al
Lines 1141-1159 Link Here
1141
	ALIGN_TEXT
1141
	ALIGN_TEXT
1142
fastmove_fault:
1142
fastmove_fault:
1143
	/* XXX ungrab FPU context atomically. */
1143
	/* XXX ungrab FPU context atomically. */
1144
	cli
1144
	cli
1145
1145
1146
	movl	PCPU(CURPCB),%edi
1146
	movl	PCPU(CURPCB),%edi
1147
	addl	$PCB_SAVEFPU,%edi
1147
	addl	$PCB_SAVEFPU,%edi
1148
	movl	%esp,%esi
1148
	movl	%esp,%esi
1149
	cld
1149
	cld
1150
	movl	$PCB_SAVEFPU_SIZE>>2,%ecx
1150
	movl	$PCB_SAVE87_SIZE>>2,%ecx
1151
	rep
1151
	rep
1152
	movsl
1152
	movsl
1153
1153
1154
	smsw	%ax
1154
	smsw	%ax
1155
	orb	$CR0_TS,%al
1155
	orb	$CR0_TS,%al
1156
	lmsw	%ax
1156
	lmsw	%ax
1157
	movl	$0,PCPU(NPXPROC)
1157
	movl	$0,PCPU(NPXPROC)
1158
1158
1159
	/* XXX end of atomic FPU context ungrab. */
1159
	/* XXX end of atomic FPU context ungrab. */
(-)sys/i386/i386/vm_machdep.c (-1 / +1 lines)
Lines 142-160 Link Here
142
		return;
142
		return;
143
	}
143
	}
144
144
145
	/* Ensure that p1's pcb is up to date. */
145
	/* Ensure that p1's pcb is up to date. */
146
#ifdef DEV_NPX
146
#ifdef DEV_NPX
147
	if (p1 == curproc)
147
	if (p1 == curproc)
148
		p1->p_addr->u_pcb.pcb_gs = rgs();
148
		p1->p_addr->u_pcb.pcb_gs = rgs();
149
	savecrit = critical_enter();
149
	savecrit = critical_enter();
150
	if (PCPU_GET(npxproc) == p1)
150
	if (PCPU_GET(npxproc) == p1)
151
		npxsave(&p1->p_addr->u_pcb.pcb_savefpu);
151
		npxsave(&p1->p_addr->u_pcb.pcb_save);
152
	critical_exit(savecrit);
152
	critical_exit(savecrit);
153
#endif
153
#endif
154
154
155
	/* Copy p1's pcb. */
155
	/* Copy p1's pcb. */
156
	p2->p_addr->u_pcb = p1->p_addr->u_pcb;
156
	p2->p_addr->u_pcb = p1->p_addr->u_pcb;
157
	pcb2 = &p2->p_addr->u_pcb;
157
	pcb2 = &p2->p_addr->u_pcb;
158
158
159
	/*
159
	/*
160
	 * Create a new fresh stack for the new process.
160
	 * Create a new fresh stack for the new process.
(-)sys/i386/include/md_var.h (+1 lines)
Lines 41-58 Link Here
41
extern	void	(*bcopy_vector) __P((const void *from, void *to, size_t len));
41
extern	void	(*bcopy_vector) __P((const void *from, void *to, size_t len));
42
extern	int	busdma_swi_pending;
42
extern	int	busdma_swi_pending;
43
extern	int	(*copyin_vector) __P((const void *udaddr, void *kaddr,
43
extern	int	(*copyin_vector) __P((const void *udaddr, void *kaddr,
44
				      size_t len));
44
				      size_t len));
45
extern	int	(*copyout_vector) __P((const void *kaddr, void *udaddr,
45
extern	int	(*copyout_vector) __P((const void *kaddr, void *udaddr,
46
				       size_t len));
46
				       size_t len));
47
extern	u_int	cpu_feature;
47
extern	u_int	cpu_feature;
48
extern	u_int	cpu_high;
48
extern	u_int	cpu_high;
49
extern	u_int	cpu_id;
49
extern	u_int	cpu_id;
50
extern	u_int	cpu_fxsr;
50
extern	char	cpu_vendor[];
51
extern	char	cpu_vendor[];
51
extern	u_int	cyrix_did;
52
extern	u_int	cyrix_did;
52
extern	char	kstack[];
53
extern	char	kstack[];
53
#ifdef PC98
54
#ifdef PC98
54
extern	int	need_pre_dma_flush;
55
extern	int	need_pre_dma_flush;
55
extern	int	need_post_dma_flush;
56
extern	int	need_post_dma_flush;
56
#endif
57
#endif
57
extern	int	nfs_diskless_valid;
58
extern	int	nfs_diskless_valid;
58
extern	void	(*ovbcopy_vector) __P((const void *from, void *to, size_t len));
59
extern	void	(*ovbcopy_vector) __P((const void *from, void *to, size_t len));
(-)sys/i386/include/npx.h (-1 / +37 lines)
Lines 79-96 Link Here
79
	 * struct and arrange to store into this struct (ending here)
79
	 * struct and arrange to store into this struct (ending here)
80
	 * before it is inspected for ptracing or for core dumps.  Some
80
	 * before it is inspected for ptracing or for core dumps.  Some
81
	 * emulators overwrite the whole struct.  We have no good way of
81
	 * emulators overwrite the whole struct.  We have no good way of
82
	 * knowing how much padding to leave.  Leave just enough for the
82
	 * knowing how much padding to leave.  Leave just enough for the
83
	 * GPL emulator's i387_union (176 bytes total).
83
	 * GPL emulator's i387_union (176 bytes total).
84
	 */
84
	 */
85
	u_char	sv_pad[64];	/* padding; used by emulators */
85
	u_char	sv_pad[64];	/* padding; used by emulators */
86
};
86
};
87
87
88
struct  envxmm {
89
	u_int16_t	en_cw;		/* control word (16bits) */
90
	u_int16_t	en_sw;		/* status word (16bits) */
91
	u_int16_t	en_tw;		/* tag word (16bits) */
92
	u_int16_t	en_opcode;	/* opcode last executed (11 bits ) */
93
	u_int32_t	en_fip;		/* floating point instruction pointer */
94
	u_int16_t	en_fcs;		/* floating code segment selector */
95
	u_int16_t	en_pad0;	/* padding */
96
	u_int32_t	en_foo;		/* floating operand offset */
97
	u_int16_t	en_fos;		/* floating operand segment selector */
98
	u_int16_t	en_pad1;	/* padding */
99
	u_int32_t	en_mxcsr;	/* SSE contorol/status register */
100
	u_int32_t	en_pad2;	/* padding */
101
};
102
103
/* Contents of each SSE extended accumulator */
104
struct	xmmacc {
105
	u_char	xmm_bytes[16];
106
};
107
108
struct  savexmm {
109
	struct	envxmm	sv_env;
110
	struct {
111
		struct fpacc87	fp_acc;
112
		u_char		fp_pad[6];	/* padding */
113
	} sv_fp[8];
114
	struct xmmacc	sv_xmm[8];
115
	u_long sv_ex_sw;	/* status word for last exception */
116
	u_char sv_pad[220];
117
};
118
119
union	savefpu {
120
	struct	save87	sv_87;
121
	struct	savexmm	sv_xmm;
122
};
123
88
/*
124
/*
89
 * The hardware default control word for i387's and later coprocessors is
125
 * The hardware default control word for i387's and later coprocessors is
90
 * 0x37F, giving:
126
 * 0x37F, giving:
91
 *
127
 *
92
 *	round to nearest
128
 *	round to nearest
93
 *	64-bit precision
129
 *	64-bit precision
94
 *	all exceptions masked.
130
 *	all exceptions masked.
95
 *
131
 *
96
 * We modify the affine mode bit and precision bits in this to give:
132
 * We modify the affine mode bit and precision bits in this to give:
Lines 102-115 Link Here
102
 * because it makes the results of calculations depend on whether
138
 * because it makes the results of calculations depend on whether
103
 * intermediate values are stored in memory or in FPU registers.
139
 * intermediate values are stored in memory or in FPU registers.
104
 */
140
 */
105
#define	__INITIAL_NPXCW__	0x127F
141
#define	__INITIAL_NPXCW__	0x127F
106
142
107
#ifdef _KERNEL
143
#ifdef _KERNEL
108
int	npxdna __P((void));
144
int	npxdna __P((void));
109
void	npxexit __P((struct proc *p));
145
void	npxexit __P((struct proc *p));
110
void	npxinit __P((int control));
146
void	npxinit __P((int control));
111
void	npxsave __P((struct save87 *addr));
147
void	npxsave __P((union savefpu *addr));
112
int	npxtrap __P((void));
148
int	npxtrap __P((void));
113
#endif
149
#endif
114
150
115
#endif /* !_MACHINE_NPX_H_ */
151
#endif /* !_MACHINE_NPX_H_ */
(-)sys/i386/include/pcb.h (-1 / +2 lines)
Lines 56-74 Link Here
56
56
57
	int     pcb_dr0;
57
	int     pcb_dr0;
58
	int     pcb_dr1;
58
	int     pcb_dr1;
59
	int     pcb_dr2;
59
	int     pcb_dr2;
60
	int     pcb_dr3;
60
	int     pcb_dr3;
61
	int     pcb_dr6;
61
	int     pcb_dr6;
62
	int     pcb_dr7;
62
	int     pcb_dr7;
63
63
64
	struct	pcb_ldt *pcb_ldt;	/* per process (user) LDT */
64
	struct	pcb_ldt *pcb_ldt;	/* per process (user) LDT */
65
	struct	save87	pcb_savefpu;	/* floating point state for 287/387 */
65
	union	savefpu	pcb_save;
66
#define	pcb_savefpu	pcb_save.sv_87
66
	u_char	pcb_flags;
67
	u_char	pcb_flags;
67
#define	FP_SOFTFP	0x01	/* process using software fltng pnt emulator */
68
#define	FP_SOFTFP	0x01	/* process using software fltng pnt emulator */
68
#define	PCB_DBREGS	0x02	/* process using debug registers */
69
#define	PCB_DBREGS	0x02	/* process using debug registers */
69
#define	PCB_NPXTRAP	0x04	/* npx trap pending */
70
#define	PCB_NPXTRAP	0x04	/* npx trap pending */
70
	caddr_t	pcb_onfault;	/* copyin/out fault recovery */
71
	caddr_t	pcb_onfault;	/* copyin/out fault recovery */
71
	int	pcb_gs;
72
	int	pcb_gs;
72
	struct	pcb_ext	*pcb_ext;	/* optional pcb extension */
73
	struct	pcb_ext	*pcb_ext;	/* optional pcb extension */
73
	u_long	__pcb_spare[3];	/* adjust to avoid core dump size changes */
74
	u_long	__pcb_spare[3];	/* adjust to avoid core dump size changes */
74
};
75
};
(-)sys/i386/include/specialreg.h (+2 lines)
Lines 87-104 Link Here
87
#define	CPUID_MCE	0x0080
87
#define	CPUID_MCE	0x0080
88
#define	CPUID_CX8	0x0100
88
#define	CPUID_CX8	0x0100
89
#define	CPUID_APIC	0x0200
89
#define	CPUID_APIC	0x0200
90
#define	CPUID_B10	0x0400
90
#define	CPUID_B10	0x0400
91
#define	CPUID_B11	0x0800
91
#define	CPUID_B11	0x0800
92
#define	CPUID_MTRR	0x1000
92
#define	CPUID_MTRR	0x1000
93
#define	CPUID_PGE	0x2000
93
#define	CPUID_PGE	0x2000
94
#define	CPUID_MCA	0x4000
94
#define	CPUID_MCA	0x4000
95
#define	CPUID_CMOV	0x8000
95
#define	CPUID_CMOV	0x8000
96
#define	CPUID_FXSR	0x01000000
97
#define	CPUID_XMM	0x02000000
96
98
97
/*
99
/*
98
 * Model-specific registers for the i386 family
100
 * Model-specific registers for the i386 family
99
 */
101
 */
100
#define MSR_P5_MC_ADDR		0x000
102
#define MSR_P5_MC_ADDR		0x000
101
#define MSR_P5_MC_TYPE		0x001
103
#define MSR_P5_MC_TYPE		0x001
102
#define MSR_TSC			0x010
104
#define MSR_TSC			0x010
103
#define MSR_APICBASE		0x01b
105
#define MSR_APICBASE		0x01b
104
#define MSR_EBL_CR_POWERON	0x02a
106
#define MSR_EBL_CR_POWERON	0x02a
(-)sys/i386/isa/npx.c (-10 / +63 lines)
Lines 29-46 Link Here
29
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32
 * SUCH DAMAGE.
32
 * SUCH DAMAGE.
33
 *
33
 *
34
 *	from: @(#)npx.c	7.2 (Berkeley) 5/12/91
34
 *	from: @(#)npx.c	7.2 (Berkeley) 5/12/91
35
 * $FreeBSD: src/sys/i386/isa/npx.c,v 1.101 2001/05/22 21:20:49 bde Exp $
35
 * $FreeBSD: src/sys/i386/isa/npx.c,v 1.101 2001/05/22 21:20:49 bde Exp $
36
 */
36
 */
37
37
38
#include "opt_cpu.h"
38
#include "opt_debug_npx.h"
39
#include "opt_debug_npx.h"
39
#include "opt_math_emulate.h"
40
#include "opt_math_emulate.h"
40
41
41
#include <sys/param.h>
42
#include <sys/param.h>
42
#include <sys/systm.h>
43
#include <sys/systm.h>
43
#include <sys/bus.h>
44
#include <sys/bus.h>
44
#include <sys/kernel.h>
45
#include <sys/kernel.h>
45
#include <sys/lock.h>
46
#include <sys/lock.h>
46
#include <sys/malloc.h>
47
#include <sys/malloc.h>
Lines 93-138 Link Here
93
94
94
#define	fldcw(addr)		__asm("fldcw %0" : : "m" (*(addr)))
95
#define	fldcw(addr)		__asm("fldcw %0" : : "m" (*(addr)))
95
#define	fnclex()		__asm("fnclex")
96
#define	fnclex()		__asm("fnclex")
96
#define	fninit()		__asm("fninit")
97
#define	fninit()		__asm("fninit")
97
#define	fnsave(addr)		__asm __volatile("fnsave %0" : "=m" (*(addr)))
98
#define	fnsave(addr)		__asm __volatile("fnsave %0" : "=m" (*(addr)))
98
#define	fnstcw(addr)		__asm __volatile("fnstcw %0" : "=m" (*(addr)))
99
#define	fnstcw(addr)		__asm __volatile("fnstcw %0" : "=m" (*(addr)))
99
#define	fnstsw(addr)		__asm __volatile("fnstsw %0" : "=m" (*(addr)))
100
#define	fnstsw(addr)		__asm __volatile("fnstsw %0" : "=m" (*(addr)))
100
#define	fp_divide_by_0()	__asm("fldz; fld1; fdiv %st,%st(1); fnop")
101
#define	fp_divide_by_0()	__asm("fldz; fld1; fdiv %st,%st(1); fnop")
101
#define	frstor(addr)		__asm("frstor %0" : : "m" (*(addr)))
102
#define	frstor(addr)		__asm("frstor %0" : : "m" (*(addr)))
103
#define fxrstor(addr)		__asm("fxrstor %0" : : "m" (*(addr)))
104
#define fxsave(addr)		__asm __volatile("fxsave %0" : "=m" (*(addr)))
102
#define	start_emulating()	__asm("smsw %%ax; orb %0,%%al; lmsw %%ax" \
105
#define	start_emulating()	__asm("smsw %%ax; orb %0,%%al; lmsw %%ax" \
103
				      : : "n" (CR0_TS) : "ax")
106
				      : : "n" (CR0_TS) : "ax")
104
#define	stop_emulating()	__asm("clts")
107
#define	stop_emulating()	__asm("clts")
105
108
106
#else	/* not __GNUC__ */
109
#else	/* not __GNUC__ */
107
110
108
void	fldcw		__P((caddr_t addr));
111
void	fldcw		__P((caddr_t addr));
109
void	fnclex		__P((void));
112
void	fnclex		__P((void));
110
void	fninit		__P((void));
113
void	fninit		__P((void));
111
void	fnsave		__P((caddr_t addr));
114
void	fnsave		__P((caddr_t addr));
112
void	fnstcw		__P((caddr_t addr));
115
void	fnstcw		__P((caddr_t addr));
113
void	fnstsw		__P((caddr_t addr));
116
void	fnstsw		__P((caddr_t addr));
114
void	fp_divide_by_0	__P((void));
117
void	fp_divide_by_0	__P((void));
115
void	frstor		__P((caddr_t addr));
118
void	frstor		__P((caddr_t addr));
119
void	fxsave		__P((caddr_t addr));
120
void	fxrstor		__P((caddr_t addr));
116
void	start_emulating	__P((void));
121
void	start_emulating	__P((void));
117
void	stop_emulating	__P((void));
122
void	stop_emulating	__P((void));
118
123
119
#endif	/* __GNUC__ */
124
#endif	/* __GNUC__ */
120
125
126
#ifdef CPU_ENABLE_SSE
127
#define FPU_STATUS_EX(pcb) \
128
	(cpu_fxsr ? \
129
		&(pcb)->pcb_save.sv_xmm.sv_ex_sw : \
130
		&(pcb)->pcb_save.sv_87.sv_ex_sw)
131
#else /* CPU_ENABLE_SSE */
132
#define FPU_STATUS_EX(pcb)	(&(pcb)->pcb_save.sv_87.sv_ex_sw)
133
#endif /* CPU_ENABLE_SSE */
134
121
typedef u_char bool_t;
135
typedef u_char bool_t;
122
136
123
static	int	npx_attach	__P((device_t dev));
137
static	int	npx_attach	__P((device_t dev));
124
static	void	npx_identify	__P((driver_t *driver, device_t parent));
138
static	void	npx_identify	__P((driver_t *driver, device_t parent));
125
#ifndef SMP
139
#ifndef SMP
126
static	void	npx_intr	__P((void *));
140
static	void	npx_intr	__P((void *));
127
#endif
141
#endif
128
static	int	npx_probe	__P((device_t dev));
142
static	int	npx_probe	__P((device_t dev));
129
static	int	npx_probe1	__P((device_t dev));
143
static	int	npx_probe1	__P((device_t dev));
144
static	void	fpusave		__P((union savefpu *));
145
static	void	fpurstor	__P((union savefpu *));
130
#ifdef I586_CPU
146
#ifdef I586_CPU
131
static	long	timezero	__P((const char *funcname,
147
static	long	timezero	__P((const char *funcname,
132
				     void (*func)(void *buf, size_t len)));
148
				     void (*func)(void *buf, size_t len)));
133
#endif /* I586_CPU */
149
#endif /* I586_CPU */
134
150
135
int	hw_float;		/* XXX currently just alias for npx_exists */
151
int	hw_float;		/* XXX currently just alias for npx_exists */
136
152
137
SYSCTL_INT(_hw,HW_FLOATINGPT, floatingpoint,
153
SYSCTL_INT(_hw,HW_FLOATINGPT, floatingpoint,
138
	CTLFLAG_RD, &hw_float, 0, 
154
	CTLFLAG_RD, &hw_float, 0, 
Lines 197-214 Link Here
197
213
198
	child = BUS_ADD_CHILD(parent, 0, "npx", 0);
214
	child = BUS_ADD_CHILD(parent, 0, "npx", 0);
199
	if (child == NULL)
215
	if (child == NULL)
200
		panic("npx_identify");
216
		panic("npx_identify");
201
}
217
}
202
218
203
#ifndef SMP
219
#ifndef SMP
204
/*
220
/*
205
 * Do minimal handling of npx interrupts to convert them to traps.
221
 * Do minimal handling of npx interrupts to convert them to traps.
222
 *
223
 * (2001/06/10) kaz@kobe1995 TODO: FPU STATUS
206
 */
224
 */
207
static void
225
static void
208
npx_intr(dummy)
226
npx_intr(dummy)
209
	void *dummy;
227
	void *dummy;
210
{
228
{
211
	struct proc *p;
229
	struct proc *p;
212
230
213
	/*
231
	/*
214
	 * The BUSY# latch must be cleared in all cases so that the next
232
	 * The BUSY# latch must be cleared in all cases so that the next
Lines 523-579 Link Here
523
}
541
}
524
542
525
/*
543
/*
526
 * Initialize floating point unit.
544
 * Initialize floating point unit.
527
 */
545
 */
528
void
546
void
529
npxinit(control)
547
npxinit(control)
530
	u_short control;
548
	u_short control;
531
{
549
{
532
	struct save87 dummy;
550
	union savefpu dummy;
533
	critical_t savecrit;
551
	critical_t savecrit;
534
552
535
	if (!npx_exists)
553
	if (!npx_exists)
536
		return;
554
		return;
537
	/*
555
	/*
538
	 * fninit has the same h/w bugs as fnsave.  Use the detoxified
556
	 * fninit has the same h/w bugs as fnsave.  Use the detoxified
539
	 * fnsave to throw away any junk in the fpu.  npxsave() initializes
557
	 * fnsave to throw away any junk in the fpu.  npxsave() initializes
540
	 * the fpu and sets npxproc = NULL as important side effects.
558
	 * the fpu and sets npxproc = NULL as important side effects.
541
	 */
559
	 */
542
	savecrit = critical_enter();
560
	savecrit = critical_enter();
543
	npxsave(&dummy);
561
	npxsave(&dummy);
544
	stop_emulating();
562
	stop_emulating();
545
	fldcw(&control);
563
	fldcw(&control);
546
	if (PCPU_GET(curpcb) != NULL)
564
	if (PCPU_GET(curpcb) != NULL)
547
		fnsave(&PCPU_GET(curpcb)->pcb_savefpu);
565
		fpusave(&PCPU_GET(curpcb)->pcb_save);
548
	start_emulating();
566
	start_emulating();
549
	critical_exit(savecrit);
567
	critical_exit(savecrit);
550
}
568
}
551
569
552
/*
570
/*
553
 * Free coprocessor (if we have it).
571
 * Free coprocessor (if we have it).
554
 */
572
 */
555
void
573
void
556
npxexit(p)
574
npxexit(p)
557
	struct proc *p;
575
	struct proc *p;
558
{
576
{
559
	critical_t savecrit;
577
	critical_t savecrit;
560
578
561
	savecrit = critical_enter();
579
	savecrit = critical_enter();
562
	if (p == PCPU_GET(npxproc))
580
	if (p == PCPU_GET(npxproc))
563
		npxsave(&PCPU_GET(curpcb)->pcb_savefpu);
581
		npxsave(&PCPU_GET(curpcb)->pcb_save);
564
	critical_exit(savecrit);
582
	critical_exit(savecrit);
565
#ifdef NPX_DEBUG
583
#ifdef NPX_DEBUG
566
	if (npx_exists) {
584
	if (npx_exists) {
567
		u_int	masked_exceptions;
585
		u_int	masked_exceptions;
568
586
569
		masked_exceptions = PCPU_GET(curpcb)->pcb_savefpu.sv_env.en_cw
587
		masked_exceptions = PCPU_GET(curpcb)->pcb_save.sv_env.en_cw
570
		    & PCPU_GET(curpcb)->pcb_savefpu.sv_env.en_sw & 0x7f;
588
		    & PCPU_GET(curpcb)->pcb_save.sv_env.en_sw & 0x7f;
571
		/*
589
		/*
572
		 * Log exceptions that would have trapped with the old
590
		 * Log exceptions that would have trapped with the old
573
		 * control word (overflow, divide by 0, and invalid operand).
591
		 * control word (overflow, divide by 0, and invalid operand).
574
		 */
592
		 */
575
		if (masked_exceptions & 0x0d)
593
		if (masked_exceptions & 0x0d)
576
			log(LOG_ERR,
594
			log(LOG_ERR,
577
	"pid %d (%s) exited with masked floating point exceptions 0x%02x\n",
595
	"pid %d (%s) exited with masked floating point exceptions 0x%02x\n",
578
			    p->p_pid, p->p_comm, masked_exceptions);
596
			    p->p_pid, p->p_comm, masked_exceptions);
579
	}
597
	}
Lines 807-853 Link Here
807
 * Implement device not available (DNA) exception
825
 * Implement device not available (DNA) exception
808
 *
826
 *
809
 * It would be better to switch FP context here (if curproc != npxproc)
827
 * It would be better to switch FP context here (if curproc != npxproc)
810
 * and not necessarily for every context switch, but it is too hard to
828
 * and not necessarily for every context switch, but it is too hard to
811
 * access foreign pcb's.
829
 * access foreign pcb's.
812
 */
830
 */
813
int
831
int
814
npxdna()
832
npxdna()
815
{
833
{
834
	/* u_long *pstatus; kaz@kobe1995 */
816
	critical_t s;
835
	critical_t s;
817
836
818
	if (!npx_exists)
837
	if (!npx_exists)
819
		return (0);
838
		return (0);
820
	if (PCPU_GET(npxproc) != NULL) {
839
	if (PCPU_GET(npxproc) != NULL) {
821
		printf("npxdna: npxproc = %p, curproc = %p\n",
840
		printf("npxdna: npxproc = %p, curproc = %p\n",
822
		       PCPU_GET(npxproc), curproc);
841
		       PCPU_GET(npxproc), curproc);
823
		panic("npxdna");
842
		panic("npxdna");
824
	}
843
	}
825
	s = critical_enter();
844
	s = critical_enter();
826
	stop_emulating();
845
	stop_emulating();
827
	/*
846
	/*
828
	 * Record new context early in case frstor causes an IRQ13.
847
	 * Record new context early in case frstor causes an IRQ13.
829
	 */
848
	 */
830
	PCPU_SET(npxproc, CURPROC);
849
	PCPU_SET(npxproc, CURPROC);
831
	PCPU_GET(curpcb)->pcb_savefpu.sv_ex_sw = 0;
850
	PCPU_GET(curpcb)->pcb_savefpu.sv_ex_sw = 0; /* kaz@kobe1995 */
851
	/* pstatus = FPU_STATUS_EX(curpcb);
852
	*pstatus = 0;	kaz@kobe1995 */
853
832
	/*
854
	/*
833
	 * The following frstor may cause an IRQ13 when the state being
855
	 * The following frstor may cause an IRQ13 when the state being
834
	 * restored has a pending error.  The error will appear to have been
856
	 * restored has a pending error.  The error will appear to have been
835
	 * triggered by the current (npx) user instruction even when that
857
	 * triggered by the current (npx) user instruction even when that
836
	 * instruction is a no-wait instruction that should not trigger an
858
	 * instruction is a no-wait instruction that should not trigger an
837
	 * error (e.g., fnclex).  On at least one 486 system all of the
859
	 * error (e.g., fnclex).  On at least one 486 system all of the
838
	 * no-wait instructions are broken the same as frstor, so our
860
	 * no-wait instructions are broken the same as frstor, so our
839
	 * treatment does not amplify the breakage.  On at least one
861
	 * treatment does not amplify the breakage.  On at least one
840
	 * 386/Cyrix 387 system, fnclex works correctly while frstor and
862
	 * 386/Cyrix 387 system, fnclex works correctly while frstor and
841
	 * fnsave are broken, so our treatment breaks fnclex if it is the
863
	 * fnsave are broken, so our treatment breaks fnclex if it is the
842
	 * first FPU instruction after a context switch.
864
	 * first FPU instruction after a context switch.
843
	 */
865
	 */
844
	frstor(&PCPU_GET(curpcb)->pcb_savefpu);
866
	fpurstor(&PCPU_GET(curpcb)->pcb_save);
845
	critical_exit(s);
867
	critical_exit(s);
846
868
847
	return (1);
869
	return (1);
848
}
870
}
849
871
850
/*
872
/*
851
 * Wrapper for fnsave instruction, partly to handle hardware bugs.  When npx
873
 * Wrapper for fnsave instruction, partly to handle hardware bugs.  When npx
852
 * exceptions are reported via IRQ13, spurious IRQ13's may be triggered by
874
 * exceptions are reported via IRQ13, spurious IRQ13's may be triggered by
853
 * no-wait npx instructions.  See the Intel application note AP-578 for
875
 * no-wait npx instructions.  See the Intel application note AP-578 for
Lines 866-890 Link Here
866
 * npxsave() atomically with checking npxproc.
888
 * npxsave() atomically with checking npxproc.
867
 *
889
 *
868
 * A previous version of npxsave() went to great lengths to excecute fnsave
890
 * A previous version of npxsave() went to great lengths to excecute fnsave
869
 * with interrupts enabled in case executing it froze the CPU.  This case
891
 * with interrupts enabled in case executing it froze the CPU.  This case
870
 * can't happen, at least for Intel CPU/NPX's.  Spurious IRQ13's don't imply
892
 * can't happen, at least for Intel CPU/NPX's.  Spurious IRQ13's don't imply
871
 * spurious freezes.
893
 * spurious freezes.
872
 */
894
 */
873
void
895
void
874
npxsave(addr)
896
npxsave(addr)
875
	struct save87 *addr;
897
	union savefpu *addr;
876
{
898
{
877
899
878
	stop_emulating();
900
	stop_emulating();
879
	fnsave(addr);
901
	fpusave(addr);
880
	start_emulating();
902
	start_emulating();
881
	PCPU_SET(npxproc, NULL);
903
	PCPU_SET(npxproc, NULL);
904
}
905
906
static void
907
fpusave(addr)
908
	union savefpu *addr;
909
{
910
#ifdef CPU_ENABLE_SSE
911
	static struct savexmm svxmm __attribute__((aligned(16)));
912
913
	if (cpu_fxsr) {
914
		fxsave(&svxmm);
915
		bcopy(&svxmm, addr, sizeof(struct savexmm));
916
		return;
917
	}
918
#endif /* CPU_ENABLE_SSE */
919
      fnsave(addr);
920
}
921
922
static void
923
fpurstor(addr)
924
	union savefpu *addr;
925
{
926
#ifdef CPU_ENABLE_SSE
927
	static struct savexmm svxmm __attribute__((aligned(16)));
928
929
	if (cpu_fxsr) {
930
		bcopy(addr, &svxmm, sizeof (struct savexmm));
931
		fxrstor(&svxmm);
932
		return;
933
	}
934
#endif /* CPU_ENABLE_SSE */
935
	frstor(addr);
882
}
936
}
883
937
884
#ifdef I586_CPU
938
#ifdef I586_CPU
885
static long
939
static long
886
timezero(funcname, func)
940
timezero(funcname, func)
887
	const char *funcname;
941
	const char *funcname;
888
	void (*func) __P((void *buf, size_t len));
942
	void (*func) __P((void *buf, size_t len));
889
943
890
{
944
{
891
- 

Return to bug 28070