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

(-)sys+/conf/options.i386 (+1 lines)
Lines 52-69 Link Here
52
CPU_LOOP_EN			opt_cpu.h
52
CPU_LOOP_EN			opt_cpu.h
53
CPU_PPRO2CELERON		opt_cpu.h
53
CPU_PPRO2CELERON		opt_cpu.h
54
CPU_RSTK_EN			opt_cpu.h
54
CPU_RSTK_EN			opt_cpu.h
55
CPU_SUSP_HLT			opt_cpu.h
55
CPU_SUSP_HLT			opt_cpu.h
56
CPU_UPGRADE_HW_CACHE		opt_cpu.h
56
CPU_UPGRADE_HW_CACHE		opt_cpu.h
57
CPU_WT_ALLOC			opt_cpu.h
57
CPU_WT_ALLOC			opt_cpu.h
58
CYRIX_CACHE_WORKS		opt_cpu.h
58
CYRIX_CACHE_WORKS		opt_cpu.h
59
CYRIX_CACHE_REALLY_WORKS	opt_cpu.h
59
CYRIX_CACHE_REALLY_WORKS	opt_cpu.h
60
NO_MEMORY_HOLE			opt_cpu.h
60
NO_MEMORY_HOLE			opt_cpu.h
61
CPU_ENABLE_SSE			opt_cpu.h
61
62
62
# The CPU type affects the endian conversion functions all over the kernel.
63
# The CPU type affects the endian conversion functions all over the kernel.
63
I386_CPU		opt_global.h
64
I386_CPU		opt_global.h
64
I486_CPU		opt_global.h
65
I486_CPU		opt_global.h
65
I586_CPU		opt_global.h
66
I586_CPU		opt_global.h
66
I686_CPU		opt_global.h
67
I686_CPU		opt_global.h
67
68
68
MAXCONS			opt_syscons.h
69
MAXCONS			opt_syscons.h
69
SC_ALT_MOUSE_IMAGE	opt_syscons.h
70
SC_ALT_MOUSE_IMAGE	opt_syscons.h
(-)sys+/i386/conf/LINT (+2 lines)
Lines 158-175 Link Here
158
#
158
#
159
# CPU_CYRIX_NO_LOCK enables weak locking for the entire address space
159
# CPU_CYRIX_NO_LOCK enables weak locking for the entire address space
160
# of Cyrix 6x86 and 6x86MX CPUs by setting the NO_LOCK bit of CCR1.
160
# of Cyrix 6x86 and 6x86MX CPUs by setting the NO_LOCK bit of CCR1.
161
# Otherwise, the NO_LOCK bit of CCR1 is cleared.  (NOTE 3)
161
# Otherwise, the NO_LOCK bit of CCR1 is cleared.  (NOTE 3)
162
#
162
#
163
# CPU_DISABLE_5X86_LSSER disables load store serialize (i.e. enables
163
# CPU_DISABLE_5X86_LSSER disables load store serialize (i.e. enables
164
# reorder).  This option should not be used if you use memory mapped
164
# reorder).  This option should not be used if you use memory mapped
165
# I/O device(s).
165
# I/O device(s).
166
#
166
#
167
# CPU_ENABLE_SSE enables SSE/MMX2 instructions support.
168
#
167
# CPU_FASTER_5X86_FPU enables faster FPU exception handler.
169
# CPU_FASTER_5X86_FPU enables faster FPU exception handler.
168
#
170
#
169
# CPU_I486_ON_386 enables CPU cache on i486 based CPU upgrade products
171
# CPU_I486_ON_386 enables CPU cache on i486 based CPU upgrade products
170
# for i386 machines.
172
# for i386 machines.
171
#
173
#
172
# CPU_IORT defines I/O clock delay time (NOTE 1).  Default values of
174
# CPU_IORT defines I/O clock delay time (NOTE 1).  Default values of
173
# I/O clock delay time on Cyrix 5x86 and 6x86 are 0 and 7,respectively
175
# I/O clock delay time on Cyrix 5x86 and 6x86 are 0 and 7,respectively
174
# (no clock delay).
176
# (no clock delay).
175
#
177
#
(-)sys+/i386/i386/genassym.c (-2 / +3 lines)
Lines 126-145 Link Here
126
ASSYM(PCB_DBREGS, PCB_DBREGS);
126
ASSYM(PCB_DBREGS, PCB_DBREGS);
127
ASSYM(PCB_EXT, offsetof(struct pcb, pcb_ext));
127
ASSYM(PCB_EXT, offsetof(struct pcb, pcb_ext));
128
128
129
#ifdef SMP
129
#ifdef SMP
130
ASSYM(PCB_MPNEST, offsetof(struct pcb, pcb_mpnest));
130
ASSYM(PCB_MPNEST, offsetof(struct pcb, pcb_mpnest));
131
#endif
131
#endif
132
132
133
ASSYM(PCB_SPARE, offsetof(struct pcb, __pcb_spare));
133
ASSYM(PCB_SPARE, offsetof(struct pcb, __pcb_spare));
134
ASSYM(PCB_FLAGS, offsetof(struct pcb, pcb_flags));
134
ASSYM(PCB_FLAGS, offsetof(struct pcb, pcb_flags));
135
ASSYM(PCB_SAVEFPU, offsetof(struct pcb, pcb_savefpu));
135
ASSYM(PCB_SAVEFPU, offsetof(struct pcb, pcb_save));
136
ASSYM(PCB_SAVEFPU_SIZE, sizeof(struct save87));
136
ASSYM(PCB_SAVEFPU_SIZE, sizeof(union savefpu));
137
ASSYM(PCB_SAVE87_SIZE, sizeof(struct save87));
137
ASSYM(PCB_ONFAULT, offsetof(struct pcb, pcb_onfault));
138
ASSYM(PCB_ONFAULT, offsetof(struct pcb, pcb_onfault));
138
139
139
#ifdef SMP
140
#ifdef SMP
140
ASSYM(PCB_SIZE, sizeof(struct pcb));
141
ASSYM(PCB_SIZE, sizeof(struct pcb));
141
#endif
142
#endif
142
143
143
ASSYM(TF_TRAPNO, offsetof(struct trapframe, tf_trapno));
144
ASSYM(TF_TRAPNO, offsetof(struct trapframe, tf_trapno));
144
ASSYM(TF_ERR, offsetof(struct trapframe, tf_err));
145
ASSYM(TF_ERR, offsetof(struct trapframe, tf_err));
145
ASSYM(TF_CS, offsetof(struct trapframe, tf_cs));
146
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.19.2.2 2000/10/15 03:09:32 nyan Exp $
29
 * $FreeBSD: src/sys/i386/i386/initcpu.c,v 1.19.2.2 2000/10/15 03:09:32 nyan 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 90-113 Link Here
90
	ALIGN_DATA		/* just to be sure */
90
	ALIGN_DATA		/* just to be sure */
91
91
92
	.globl	HIDENAME(tmpstk)
92
	.globl	HIDENAME(tmpstk)
93
	.space	0x2000		/* space for tmpstk - temporary stack */
93
	.space	0x2000		/* space for tmpstk - temporary stack */
94
HIDENAME(tmpstk):
94
HIDENAME(tmpstk):
95
95
96
	.globl	_boothowto,_bootdev
96
	.globl	_boothowto,_bootdev
97
97
98
	.globl	_cpu,_cpu_vendor,_cpu_id,_bootinfo
98
	.globl	_cpu,_cpu_vendor,_cpu_id,_bootinfo
99
	.globl	_cpu_high, _cpu_feature
99
	.globl	_cpu_high, _cpu_feature, _cpu_fxsr
100
100
101
_cpu:		.long	0			/* are we 386, 386sx, or 486 */
101
_cpu:		.long	0			/* are we 386, 386sx, or 486 */
102
_cpu_id:	.long	0			/* stepping ID */
102
_cpu_id:	.long	0			/* stepping ID */
103
_cpu_high:	.long	0			/* highest arg to CPUID */
103
_cpu_high:	.long	0			/* highest arg to CPUID */
104
_cpu_feature:	.long	0			/* features */
104
_cpu_feature:	.long	0			/* features */
105
_cpu_fxsr:	.long	0			/* use fxsave/fxrstor instruction */
105
_cpu_vendor:	.space	20			/* CPU origin code */
106
_cpu_vendor:	.space	20			/* CPU origin code */
106
_bootinfo:	.space	BOOTINFO_SIZE		/* bootinfo that we can handle */
107
_bootinfo:	.space	BOOTINFO_SIZE		/* bootinfo that we can handle */
107
108
108
_KERNend:	.long	0			/* phys addr end of kernel (just after bss) */
109
_KERNend:	.long	0			/* phys addr end of kernel (just after bss) */
109
physfree:	.long	0			/* phys addr of next free page */
110
physfree:	.long	0			/* phys addr of next free page */
110
111
111
#ifdef SMP
112
#ifdef SMP
112
		.globl	_cpu0prvpage
113
		.globl	_cpu0prvpage
113
cpu0pp:		.long	0			/* phys addr cpu0 private pg */
114
cpu0pp:		.long	0			/* phys addr cpu0 private pg */
(-)sys+/i386/i386/machdep.c (-4 / +76 lines)
Lines 119-136 Link Here
119
extern void dblfault_handler __P((void));
119
extern void dblfault_handler __P((void));
120
120
121
extern void printcpuinfo(void);	/* XXX header file */
121
extern void printcpuinfo(void);	/* XXX header file */
122
extern void earlysetcpuclass(void);	/* same header file */
122
extern void earlysetcpuclass(void);	/* same header file */
123
extern void finishidentcpu(void);
123
extern void finishidentcpu(void);
124
extern void panicifcpuunsupported(void);
124
extern void panicifcpuunsupported(void);
125
extern void initializecpu(void);
125
extern void initializecpu(void);
126
126
127
static void cpu_startup __P((void *));
127
static void cpu_startup __P((void *));
128
#ifdef CPU_ENABLE_SSE
129
static void set_fpregs_xmm __P((struct save87 *, struct savexmm *));
130
static void fill_fpregs_xmm __P((struct savexmm *, struct save87 *));
131
#endif /* CPU_ENABLE_SSE */
128
SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL)
132
SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL)
129
133
130
static MALLOC_DEFINE(M_MBUF, "mbuf", "mbuf");
134
static MALLOC_DEFINE(M_MBUF, "mbuf", "mbuf");
131
135
132
int	_udatasel, _ucodesel;
136
int	_udatasel, _ucodesel;
133
u_int	atdevbase;
137
u_int	atdevbase;
134
138
135
#if defined(SWTCH_OPTIM_STATS)
139
#if defined(SWTCH_OPTIM_STATS)
136
extern int swtch_optim_stats;
140
extern int swtch_optim_stats;
Lines 2076-2095 Link Here
2076
		tp = p->p_md.md_regs;
2080
		tp = p->p_md.md_regs;
2077
		frame_copy = *tp;
2081
		frame_copy = *tp;
2078
		*(int *)((char *)&frame_copy + (off - min)) = data;
2082
		*(int *)((char *)&frame_copy + (off - min)) = data;
2079
		if (!EFL_SECURE(frame_copy.tf_eflags, tp->tf_eflags) ||
2083
		if (!EFL_SECURE(frame_copy.tf_eflags, tp->tf_eflags) ||
2080
		    !CS_SECURE(frame_copy.tf_cs))
2084
		    !CS_SECURE(frame_copy.tf_cs))
2081
			return (EINVAL);
2085
			return (EINVAL);
2082
		*(int*)((char *)p->p_addr + off) = data;
2086
		*(int*)((char *)p->p_addr + off) = data;
2083
		return (0);
2087
		return (0);
2084
	}
2088
	}
2085
	min = offsetof(struct user, u_pcb) + offsetof(struct pcb, pcb_savefpu);
2089
	min = offsetof(struct user, u_pcb) + offsetof(struct pcb, pcb_save);
2086
	if (off >= min && off <= min + sizeof(struct save87) - sizeof(int)) {
2090
	if (off >= min && off <= min + sizeof(union savefpu) - sizeof(int)) {
2087
		*(int*)((char *)p->p_addr + off) = data;
2091
		*(int*)((char *)p->p_addr + off) = data;
2088
		return (0);
2092
		return (0);
2089
	}
2093
	}
2090
	return (EFAULT);
2094
	return (EFAULT);
2091
}
2095
}
2092
2096
2093
int
2097
int
2094
fill_regs(p, regs)
2098
fill_regs(p, regs)
2095
	struct proc *p;
2099
	struct proc *p;
Lines 2145-2177 Link Here
2145
	tp->tf_cs = regs->r_cs;
2149
	tp->tf_cs = regs->r_cs;
2146
	tp->tf_eflags = regs->r_eflags;
2150
	tp->tf_eflags = regs->r_eflags;
2147
	tp->tf_esp = regs->r_esp;
2151
	tp->tf_esp = regs->r_esp;
2148
	tp->tf_ss = regs->r_ss;
2152
	tp->tf_ss = regs->r_ss;
2149
	pcb = &p->p_addr->u_pcb;
2153
	pcb = &p->p_addr->u_pcb;
2150
	pcb->pcb_gs = regs->r_gs;
2154
	pcb->pcb_gs = regs->r_gs;
2151
	return (0);
2155
	return (0);
2152
}
2156
}
2153
2157
2158
#ifdef CPU_ENABLE_SSE
2159
static void
2160
fill_fpregs_xmm(sv_xmm, sv_87)
2161
	struct savexmm *sv_xmm;
2162
	struct save87 *sv_87;
2163
{
2164
	register struct env87 *penv_87 = &sv_87->sv_env;
2165
	register struct envxmm *penv_xmm = &sv_xmm->sv_env;
2166
	int i;
2167
2168
	/* FPU control/status */
2169
	penv_87->en_cw = penv_xmm->en_cw;
2170
	penv_87->en_sw = penv_xmm->en_sw;
2171
	penv_87->en_tw = penv_xmm->en_tw;
2172
	penv_87->en_fip = penv_xmm->en_fip;
2173
	penv_87->en_fcs = penv_xmm->en_fcs;
2174
	penv_87->en_opcode = penv_xmm->en_opcode;
2175
	penv_87->en_foo = penv_xmm->en_foo;
2176
	penv_87->en_fos = penv_xmm->en_fos;
2177
2178
	/* FPU registers */
2179
	for (i = 0; i < 8; ++i)
2180
		sv_87->sv_ac[i] = sv_xmm->sv_fp[i].fp_acc;
2181
2182
	sv_87->sv_ex_sw = sv_xmm->sv_ex_sw;
2183
}
2184
2185
static void
2186
set_fpregs_xmm(sv_87, sv_xmm)
2187
	struct save87 *sv_87;
2188
	struct savexmm *sv_xmm;
2189
{
2190
	register struct env87 *penv_87 = &sv_87->sv_env;
2191
	register struct envxmm *penv_xmm = &sv_xmm->sv_env;
2192
	int i;
2193
2194
/* FPU control/status */
2195
	penv_xmm->en_cw = penv_87->en_cw;
2196
	penv_xmm->en_sw = penv_87->en_sw;
2197
	penv_xmm->en_tw = penv_87->en_tw;
2198
	penv_xmm->en_fip = penv_87->en_fip;
2199
	penv_xmm->en_fcs = penv_87->en_fcs;
2200
	penv_xmm->en_opcode = penv_87->en_opcode;
2201
	penv_xmm->en_foo = penv_87->en_foo;
2202
	penv_xmm->en_fos = penv_87->en_fos;
2203
2204
	/* FPU registers */
2205
	for (i = 0; i < 8; ++i)
2206
		sv_xmm->sv_fp[i].fp_acc = sv_87->sv_ac[i];
2207
2208
	sv_xmm->sv_ex_sw = sv_87->sv_ex_sw;
2209
}
2210
#endif /* CPU_ENABLE_SSE */
2211
2154
int
2212
int
2155
fill_fpregs(p, fpregs)
2213
fill_fpregs(p, fpregs)
2156
	struct proc *p;
2214
	struct proc *p;
2157
	struct fpreg *fpregs;
2215
	struct fpreg *fpregs;
2158
{
2216
{
2159
	bcopy(&p->p_addr->u_pcb.pcb_savefpu, fpregs, sizeof *fpregs);
2217
#ifdef CPU_ENABLE_SSE
2218
	if (cpu_fxsr) {
2219
		fill_fpregs_xmm(&p->p_addr->u_pcb.pcb_save.sv_xmm,
2220
						(struct save87 *)fpregs);
2221
		return (0);
2222
	}
2223
#endif /* CPU_ENABLE_SSE */
2224
	bcopy(&p->p_addr->u_pcb.pcb_save.sv_87, fpregs, sizeof *fpregs);
2160
	return (0);
2225
	return (0);
2161
}
2226
}
2162
2227
2163
int
2228
int
2164
set_fpregs(p, fpregs)
2229
set_fpregs(p, fpregs)
2165
	struct proc *p;
2230
	struct proc *p;
2166
	struct fpreg *fpregs;
2231
	struct fpreg *fpregs;
2167
{
2232
{
2168
	bcopy(fpregs, &p->p_addr->u_pcb.pcb_savefpu, sizeof *fpregs);
2233
#ifdef CPU_ENABLE_SSE
2234
	if (cpu_fxsr) {
2235
		set_fpregs_xmm((struct save87 *)fpregs,
2236
					&p->p_addr->u_pcb.pcb_save.sv_xmm);
2237
		return (0);
2238
	}
2239
#endif /* CPU_ENABLE_SSE */
2240
	bcopy(fpregs, &p->p_addr->u_pcb.pcb_save.sv_87, sizeof *fpregs);
2169
	return (0);
2241
	return (0);
2170
}
2242
}
2171
2243
2172
int
2244
int
2173
fill_dbregs(p, dbregs)
2245
fill_dbregs(p, dbregs)
2174
	struct proc *p;
2246
	struct proc *p;
2175
	struct dbreg *dbregs;
2247
	struct dbreg *dbregs;
2176
{
2248
{
2177
	struct pcb *pcb;
2249
	struct pcb *pcb;
(-)sys+/i386/i386/mp_machdep.c (+9 lines)
Lines 229-246 Link Here
229
#define MP_ENABLE_POST		0x14
229
#define MP_ENABLE_POST		0x14
230
#define MPTABLE_PASS2_POST	0x15
230
#define MPTABLE_PASS2_POST	0x15
231
231
232
#define START_ALL_APS_POST	0x16
232
#define START_ALL_APS_POST	0x16
233
#define INSTALL_AP_TRAMP_POST	0x17
233
#define INSTALL_AP_TRAMP_POST	0x17
234
#define START_AP_POST		0x18
234
#define START_AP_POST		0x18
235
235
236
#define MP_ANNOUNCE_POST	0x19
236
#define MP_ANNOUNCE_POST	0x19
237
237
238
#if defined(CPU_ENABLE_SSE)
239
extern void    init_sse(void);
240
#endif
241
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
245
int	bsp_apic_ready = 0;	/* flags useability of BSP apic */
249
int	bsp_apic_ready = 0;	/* flags useability of BSP apic */
246
int	mp_ncpus;		/* # of CPUs, including BSP */
250
int	mp_ncpus;		/* # of CPUs, including BSP */
Lines 2392-2409 Link Here
2392
	other_cpus = all_cpus & ~(1 << cpuid);
2396
	other_cpus = all_cpus & ~(1 << cpuid);
2393
2397
2394
	printf("SMP: AP CPU #%d Launched!\n", cpuid);
2398
	printf("SMP: AP CPU #%d Launched!\n", cpuid);
2395
2399
2396
	/* XXX FIXME: i386 specific, and redundant: Setup the FPU. */
2400
	/* XXX FIXME: i386 specific, and redundant: Setup the FPU. */
2397
	load_cr0((rcr0() & ~CR0_EM) | CR0_MP | CR0_NE | CR0_TS);
2401
	load_cr0((rcr0() & ~CR0_EM) | CR0_MP | CR0_NE | CR0_TS);
2398
2402
2399
	/* set up FPU state on the AP */
2403
	/* set up FPU state on the AP */
2400
	npxinit(__INITIAL_NPXCW__);
2404
	npxinit(__INITIAL_NPXCW__);
2405
2406
	/* Setup the SSE */
2407
#if defined(CPU_ENABLE_SSE)
2408
	init_sse();
2409
#endif
2401
2410
2402
	/* A quick check from sanity claus */
2411
	/* A quick check from sanity claus */
2403
	apic_id = (apic_id_to_logical[(lapic.id & 0x0f000000) >> 24]);
2412
	apic_id = (apic_id_to_logical[(lapic.id & 0x0f000000) >> 24]);
2404
	if (cpuid != apic_id) {
2413
	if (cpuid != apic_id) {
2405
		printf("SMP: cpuid = %d\n", cpuid);
2414
		printf("SMP: cpuid = %d\n", cpuid);
2406
		printf("SMP: apic_id = %d\n", apic_id);
2415
		printf("SMP: apic_id = %d\n", apic_id);
2407
		printf("PTD[MPPTDI] = %p\n", (void *)PTD[MPPTDI]);
2416
		printf("PTD[MPPTDI] = %p\n", (void *)PTD[MPPTDI]);
2408
		panic("cpuid mismatch! boom!!");
2417
		panic("cpuid mismatch! boom!!");
2409
	}
2418
	}
(-)sys+/i386/i386/support.s (-4 / +4 lines)
Lines 948-966 Link Here
948
	src in %esi
948
	src in %esi
949
	dst in %edi
949
	dst in %edi
950
	len in %ecx		XXX changed to on stack for profiling
950
	len in %ecx		XXX changed to on stack for profiling
951
	uses %eax and %edx for tmp. storage
951
	uses %eax and %edx for tmp. storage
952
 */
952
 */
953
/* XXX use ENTRY() to get profiling.  fastmove() is actually a non-entry. */
953
/* XXX use ENTRY() to get profiling.  fastmove() is actually a non-entry. */
954
ENTRY(fastmove)
954
ENTRY(fastmove)
955
	pushl	%ebp
955
	pushl	%ebp
956
	movl	%esp,%ebp
956
	movl	%esp,%ebp
957
	subl	$PCB_SAVEFPU_SIZE+3*4,%esp
957
	subl	$PCB_SAVE87_SIZE+3*4,%esp
958
958
959
	movl	8(%ebp),%ecx
959
	movl	8(%ebp),%ecx
960
	cmpl	$63,%ecx
960
	cmpl	$63,%ecx
961
	jbe	fastmove_tail
961
	jbe	fastmove_tail
962
962
963
	testl	$7,%esi	/* check if src addr is multiple of 8 */
963
	testl	$7,%esi	/* check if src addr is multiple of 8 */
964
	jnz	fastmove_tail
964
	jnz	fastmove_tail
965
965
966
	testl	$7,%edi	/* check if dst addr is multiple of 8 */
966
	testl	$7,%edi	/* check if dst addr is multiple of 8 */
Lines 987-1005 Link Here
987
 */
987
 */
988
/* tmp = curpcb->pcb_savefpu; */
988
/* tmp = curpcb->pcb_savefpu; */
989
	movl	%ecx,-12(%ebp)
989
	movl	%ecx,-12(%ebp)
990
	movl	%esi,-8(%ebp)
990
	movl	%esi,-8(%ebp)
991
	movl	%edi,-4(%ebp)
991
	movl	%edi,-4(%ebp)
992
	movl	%esp,%edi
992
	movl	%esp,%edi
993
	movl	_curpcb,%esi
993
	movl	_curpcb,%esi
994
	addl	$PCB_SAVEFPU,%esi
994
	addl	$PCB_SAVEFPU,%esi
995
	cld
995
	cld
996
	movl	$PCB_SAVEFPU_SIZE>>2,%ecx
996
	movl	$PCB_SAVE87_SIZE>>2,%ecx
997
	rep
997
	rep
998
	movsl
998
	movsl
999
	movl	-12(%ebp),%ecx
999
	movl	-12(%ebp),%ecx
1000
	movl	-8(%ebp),%esi
1000
	movl	-8(%ebp),%esi
1001
	movl	-4(%ebp),%edi
1001
	movl	-4(%ebp),%edi
1002
/* stop_emulating(); */
1002
/* stop_emulating(); */
1003
	clts
1003
	clts
1004
/* npxproc = curproc; */
1004
/* npxproc = curproc; */
1005
	movl	_curproc,%eax
1005
	movl	_curproc,%eax
Lines 1064-1082 Link Here
1064
1064
1065
/* curpcb->pcb_savefpu = tmp; */
1065
/* curpcb->pcb_savefpu = tmp; */
1066
	movl	%ecx,-12(%ebp)
1066
	movl	%ecx,-12(%ebp)
1067
	movl	%esi,-8(%ebp)
1067
	movl	%esi,-8(%ebp)
1068
	movl	%edi,-4(%ebp)
1068
	movl	%edi,-4(%ebp)
1069
	movl	_curpcb,%edi
1069
	movl	_curpcb,%edi
1070
	addl	$PCB_SAVEFPU,%edi
1070
	addl	$PCB_SAVEFPU,%edi
1071
	movl	%esp,%esi
1071
	movl	%esp,%esi
1072
	cld
1072
	cld
1073
	movl	$PCB_SAVEFPU_SIZE>>2,%ecx
1073
	movl	$PCB_SAVE87_SIZE>>2,%ecx
1074
	rep
1074
	rep
1075
	movsl
1075
	movsl
1076
	movl	-12(%ebp),%ecx
1076
	movl	-12(%ebp),%ecx
1077
	movl	-8(%ebp),%esi
1077
	movl	-8(%ebp),%esi
1078
	movl	-4(%ebp),%edi
1078
	movl	-4(%ebp),%edi
1079
1079
1080
/* start_emulating(); */
1080
/* start_emulating(); */
1081
	smsw	%ax
1081
	smsw	%ax
1082
	orb	$CR0_TS,%al
1082
	orb	$CR0_TS,%al
Lines 1103-1121 Link Here
1103
	popl	%ebp
1103
	popl	%ebp
1104
	ret
1104
	ret
1105
1105
1106
	ALIGN_TEXT
1106
	ALIGN_TEXT
1107
fastmove_fault:
1107
fastmove_fault:
1108
	movl	_curpcb,%edi
1108
	movl	_curpcb,%edi
1109
	addl	$PCB_SAVEFPU,%edi
1109
	addl	$PCB_SAVEFPU,%edi
1110
	movl	%esp,%esi
1110
	movl	%esp,%esi
1111
	cld
1111
	cld
1112
	movl	$PCB_SAVEFPU_SIZE>>2,%ecx
1112
	movl	$PCB_SAVE87_SIZE>>2,%ecx
1113
	rep
1113
	rep
1114
	movsl
1114
	movsl
1115
1115
1116
	smsw	%ax
1116
	smsw	%ax
1117
	orb	$CR0_TS,%al
1117
	orb	$CR0_TS,%al
1118
	lmsw	%ax
1118
	lmsw	%ax
1119
	movl	$0,_npxproc
1119
	movl	$0,_npxproc
1120
1120
1121
fastmove_tail_fault:
1121
fastmove_tail_fault:
(-)sys+/i386/i386/vm_machdep.c (-1 / +1 lines)
Lines 135-153 Link Here
135
			}
135
			}
136
		}
136
		}
137
#endif
137
#endif
138
		return;
138
		return;
139
	}
139
	}
140
140
141
#if NNPX > 0
141
#if NNPX > 0
142
	/* Ensure that p1's pcb is up to date. */
142
	/* Ensure that p1's pcb is up to date. */
143
	if (npxproc == p1)
143
	if (npxproc == p1)
144
		npxsave(&p1->p_addr->u_pcb.pcb_savefpu);
144
		npxsave(&p1->p_addr->u_pcb.pcb_save);
145
#endif
145
#endif
146
146
147
	/* Copy p1's pcb. */
147
	/* Copy p1's pcb. */
148
	p2->p_addr->u_pcb = p1->p_addr->u_pcb;
148
	p2->p_addr->u_pcb = p1->p_addr->u_pcb;
149
	pcb2 = &p2->p_addr->u_pcb;
149
	pcb2 = &p2->p_addr->u_pcb;
150
150
151
	/*
151
	/*
152
	 * Create a new fresh stack for the new process.
152
	 * Create a new fresh stack for the new process.
153
	 * Copy the trap frame for the return to user mode as if from a
153
	 * Copy the trap frame for the return to user mode as if from a
(-)sys+/i386/include/asnames.h (+1 lines)
Lines 185-202 Link Here
185
#define _copyin_vector			copyin_vector
185
#define _copyin_vector			copyin_vector
186
#define _copyout_vector			copyout_vector
186
#define _copyout_vector			copyout_vector
187
#define _cpl				cpl
187
#define _cpl				cpl
188
#define _cpl_lock			cpl_lock
188
#define _cpl_lock			cpl_lock
189
#define _cpu				cpu
189
#define _cpu				cpu
190
#define _cpu0prvpage			cpu0prvpage
190
#define _cpu0prvpage			cpu0prvpage
191
#define _cpu_apic_versions		cpu_apic_versions
191
#define _cpu_apic_versions		cpu_apic_versions
192
#define _cpu_class			cpu_class
192
#define _cpu_class			cpu_class
193
#define _cpu_feature			cpu_feature
193
#define _cpu_feature			cpu_feature
194
#define _cpu_fxsr			cpu_fxsr
194
#define _cpu_high			cpu_high
195
#define _cpu_high			cpu_high
195
#define _cpu_id				cpu_id
196
#define _cpu_id				cpu_id
196
#define _cpu_num_to_apic_id		cpu_num_to_apic_id
197
#define _cpu_num_to_apic_id		cpu_num_to_apic_id
197
#define _cpu_switch			cpu_switch
198
#define _cpu_switch			cpu_switch
198
#define _cpu_vendor			cpu_vendor
199
#define _cpu_vendor			cpu_vendor
199
#define _default_halt			default_halt
200
#define _default_halt			default_halt
200
#define _denormal_operand		denormal_operand
201
#define _denormal_operand		denormal_operand
201
#define _div_small			div_small
202
#define _div_small			div_small
202
#define _divide_by_zero			divide_by_zero
203
#define _divide_by_zero			divide_by_zero
(-)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	void	(*netisrs[32]) __P((void));
58
extern	void	(*netisrs[32]) __P((void));
58
extern	int	nfs_diskless_valid;
59
extern	int	nfs_diskless_valid;
(-)sys+/i386/include/npx.h (-1 / +37 lines)
Lines 81-98 Link Here
81
	 * struct and arrange to store into this struct (ending here)
81
	 * struct and arrange to store into this struct (ending here)
82
	 * before it is inspected for ptracing or for core dumps.  Some
82
	 * before it is inspected for ptracing or for core dumps.  Some
83
	 * emulators overwrite the whole struct.  We have no good way of
83
	 * emulators overwrite the whole struct.  We have no good way of
84
	 * knowing how much padding to leave.  Leave just enough for the
84
	 * knowing how much padding to leave.  Leave just enough for the
85
	 * GPL emulator's i387_union (176 bytes total).
85
	 * GPL emulator's i387_union (176 bytes total).
86
	 */
86
	 */
87
	u_char	sv_pad[64];	/* padding; used by emulators */
87
	u_char	sv_pad[64];	/* padding; used by emulators */
88
};
88
};
89
89
90
struct  envxmm {
91
	u_int16_t	en_cw;		/* control word (16bits) */
92
	u_int16_t	en_sw;		/* status word (16bits) */
93
	u_int16_t	en_tw;		/* tag word (16bits) */
94
	u_int16_t	en_opcode;	/* opcode last executed (11 bits ) */
95
	u_int32_t	en_fip;		/* floating point instruction pointer */
96
	u_int16_t	en_fcs;		/* floating code segment selector */
97
	u_int16_t	en_pad0;	/* padding */
98
	u_int32_t	en_foo;		/* floating operand offset */
99
	u_int16_t	en_fos;		/* floating operand segment selector */
100
	u_int16_t	en_pad1;	/* padding */
101
	u_int32_t	en_mxcsr;	/* SSE sontorol/status register */
102
	u_int32_t	en_pad2;	/* padding */
103
};
104
105
/* Contents of each SSE extended accumulator */
106
struct	xmmacc {
107
	u_char	xmm_bytes[16];
108
};
109
110
struct  savexmm {
111
	struct	envxmm	sv_env;
112
	struct {
113
		struct fpacc87	fp_acc;
114
		u_char		fp_pad[6];	/* padding */
115
	} sv_fp[8];
116
	struct xmmacc	sv_xmm[8];
117
	u_long sv_ex_sw;	/* status word for last exception */
118
	u_char sv_pad[220];
119
};
120
121
union	savefpu {
122
	struct	save87	sv_87;
123
	struct	savexmm	sv_xmm;
124
};
125
90
/*
126
/*
91
 * The hardware default control word for i387's and later coprocessors is
127
 * The hardware default control word for i387's and later coprocessors is
92
 * 0x37F, giving:
128
 * 0x37F, giving:
93
 *
129
 *
94
 *	round to nearest
130
 *	round to nearest
95
 *	64-bit precision
131
 *	64-bit precision
96
 *	all exceptions masked.
132
 *	all exceptions masked.
97
 *
133
 *
98
 * We modify the affine mode bit and precision bits in this to give:
134
 * We modify the affine mode bit and precision bits in this to give:
Lines 108-120 Link Here
108
144
109
#ifdef _KERNEL
145
#ifdef _KERNEL
110
#ifndef npxproc
146
#ifndef npxproc
111
extern struct proc *npxproc;
147
extern struct proc *npxproc;
112
#endif
148
#endif
113
149
114
int	npxdna __P((void));
150
int	npxdna __P((void));
115
void	npxexit __P((struct proc *p));
151
void	npxexit __P((struct proc *p));
116
void	npxinit __P((int control));
152
void	npxinit __P((int control));
117
void	npxsave __P((struct save87 *addr));
153
void	npxsave __P((union savefpu *addr));
118
#endif
154
#endif
119
155
120
#endif /* !_MACHINE_NPX_H_ */
156
#endif /* !_MACHINE_NPX_H_ */
(-)sys+/i386/include/pcb.h (-1 / +2 lines)
Lines 61-79 Link Here
61
	int     pcb_dr3;
61
	int     pcb_dr3;
62
	int     pcb_dr6;
62
	int     pcb_dr6;
63
	int     pcb_dr7;
63
	int     pcb_dr7;
64
64
65
#ifdef USER_LDT
65
#ifdef USER_LDT
66
	struct	pcb_ldt *pcb_ldt;	/* per process (user) LDT */
66
	struct	pcb_ldt *pcb_ldt;	/* per process (user) LDT */
67
#else
67
#else
68
	struct	pcb_ldt	*pcb_ldt_dontuse;
68
	struct	pcb_ldt	*pcb_ldt_dontuse;
69
#endif
69
#endif
70
	struct	save87	pcb_savefpu;	/* floating point state for 287/387 */
70
	union	savefpu	pcb_save;
71
#define pcb_savefpu	pcb_save.sv_87
71
	u_char	pcb_flags;
72
	u_char	pcb_flags;
72
#define	FP_SOFTFP	0x01	/* process using software fltng pnt emulator */
73
#define	FP_SOFTFP	0x01	/* process using software fltng pnt emulator */
73
#define	PCB_DBREGS	0x02	/* process using debug registers */
74
#define	PCB_DBREGS	0x02	/* process using debug registers */
74
	caddr_t	pcb_onfault;	/* copyin/out fault recovery */
75
	caddr_t	pcb_onfault;	/* copyin/out fault recovery */
75
#ifdef SMP
76
#ifdef SMP
76
	u_long	pcb_mpnest;
77
	u_long	pcb_mpnest;
77
#else
78
#else
78
	u_long	pcb_mpnest_dontuse;
79
	u_long	pcb_mpnest_dontuse;
79
#endif
80
#endif
(-)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 (-13 / +67 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.80 2000/01/29 16:17:36 peter Exp $
35
 * $FreeBSD: src/sys/i386/isa/npx.c,v 1.80 2000/01/29 16:17:36 peter 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/malloc.h>
46
#include <sys/malloc.h>
46
#include <sys/module.h>
47
#include <sys/module.h>
Lines 90-134 Link Here
90
#define	fldcw(addr)		__asm("fldcw %0" : : "m" (*(addr)))
91
#define	fldcw(addr)		__asm("fldcw %0" : : "m" (*(addr)))
91
#define	fnclex()		__asm("fnclex")
92
#define	fnclex()		__asm("fnclex")
92
#define	fninit()		__asm("fninit")
93
#define	fninit()		__asm("fninit")
93
#define	fnop()			__asm("fnop")
94
#define	fnop()			__asm("fnop")
94
#define	fnsave(addr)		__asm __volatile("fnsave %0" : "=m" (*(addr)))
95
#define	fnsave(addr)		__asm __volatile("fnsave %0" : "=m" (*(addr)))
95
#define	fnstcw(addr)		__asm __volatile("fnstcw %0" : "=m" (*(addr)))
96
#define	fnstcw(addr)		__asm __volatile("fnstcw %0" : "=m" (*(addr)))
96
#define	fnstsw(addr)		__asm __volatile("fnstsw %0" : "=m" (*(addr)))
97
#define	fnstsw(addr)		__asm __volatile("fnstsw %0" : "=m" (*(addr)))
97
#define	fp_divide_by_0()	__asm("fldz; fld1; fdiv %st,%st(1); fnop")
98
#define	fp_divide_by_0()	__asm("fldz; fld1; fdiv %st,%st(1); fnop")
98
#define	frstor(addr)		__asm("frstor %0" : : "m" (*(addr)))
99
#define	frstor(addr)		__asm("frstor %0" : : "m" (*(addr)))
100
#define	fxrstor(addr)		__asm("fxrstor %0" : : "m" (*(addr)))
101
#define	fxsave(addr)		__asm __volatile("fxsave %0" : "=m" (*(addr)))
99
#define	start_emulating()	__asm("smsw %%ax; orb %0,%%al; lmsw %%ax" \
102
#define	start_emulating()	__asm("smsw %%ax; orb %0,%%al; lmsw %%ax" \
100
				      : : "n" (CR0_TS) : "ax")
103
				      : : "n" (CR0_TS) : "ax")
101
#define	stop_emulating()	__asm("clts")
104
#define	stop_emulating()	__asm("clts")
102
105
103
#else	/* not __GNUC__ */
106
#else	/* not __GNUC__ */
104
107
105
void	fldcw		__P((caddr_t addr));
108
void	fldcw		__P((caddr_t addr));
106
void	fnclex		__P((void));
109
void	fnclex		__P((void));
107
void	fninit		__P((void));
110
void	fninit		__P((void));
108
void	fnop		__P((void));
111
void	fnop		__P((void));
109
void	fnsave		__P((caddr_t addr));
112
void	fnsave		__P((caddr_t addr));
110
void	fnstcw		__P((caddr_t addr));
113
void	fnstcw		__P((caddr_t addr));
111
void	fnstsw		__P((caddr_t addr));
114
void	fnstsw		__P((caddr_t addr));
112
void	fp_divide_by_0	__P((void));
115
void	fp_divide_by_0	__P((void));
113
void	frstor		__P((caddr_t addr));
116
void	frstor		__P((caddr_t addr));
117
void	fxsave		__P((caddr_t addr));
118
void	fxrstor		__P((caddr_t addr));
114
void	start_emulating	__P((void));
119
void	start_emulating	__P((void));
115
void	stop_emulating	__P((void));
120
void	stop_emulating	__P((void));
116
121
117
#endif	/* __GNUC__ */
122
#endif	/* __GNUC__ */
118
123
124
#ifdef CPU_ENABLE_SSE
125
#define FPU_STATUS_EX(pcb) \
126
	(cpu_fxsr ? \
127
		&(pcb)->pcb_save.sv_xmm.sv_ex_sw : \
128
		&(pcb)->pcb_save.sv_87.sv_ex_sw)
129
#else /* CPU_ENABLE_SSE */
130
#define FPU_STATUS_EX(pcb)	(&(pcb)->pcb_save.sv_87.sv_ex_sw)
131
#endif /* CPU_ENABLE_SSE */
132
119
typedef u_char bool_t;
133
typedef u_char bool_t;
120
134
121
static	int	npx_attach	__P((device_t dev));
135
static	int	npx_attach	__P((device_t dev));
122
	void	npx_intr	__P((void *));
136
	void	npx_intr	__P((void *));
123
static	void	npx_identify	__P((driver_t *driver, device_t parent));
137
static	void	npx_identify	__P((driver_t *driver, device_t parent));
124
static	int	npx_probe	__P((device_t dev));
138
static	int	npx_probe	__P((device_t dev));
125
static	int	npx_probe1	__P((device_t dev));
139
static	int	npx_probe1	__P((device_t dev));
140
static	void	fpusave		__P((union savefpu *));
141
static	void	fpurstor	__P((union savefpu *));
126
#ifdef I586_CPU
142
#ifdef I586_CPU
127
static	long	timezero	__P((const char *funcname,
143
static	long	timezero	__P((const char *funcname,
128
				     void (*func)(void *buf, size_t len)));
144
				     void (*func)(void *buf, size_t len)));
129
#endif /* I586_CPU */
145
#endif /* I586_CPU */
130
146
131
int	hw_float;		/* XXX currently just alias for npx_exists */
147
int	hw_float;		/* XXX currently just alias for npx_exists */
132
148
133
SYSCTL_INT(_hw,HW_FLOATINGPT, floatingpoint,
149
SYSCTL_INT(_hw,HW_FLOATINGPT, floatingpoint,
134
	CTLFLAG_RD, &hw_float, 0, 
150
	CTLFLAG_RD, &hw_float, 0, 
Lines 468-512 Link Here
468
}
484
}
469
485
470
/*
486
/*
471
 * Initialize floating point unit.
487
 * Initialize floating point unit.
472
 */
488
 */
473
void
489
void
474
npxinit(control)
490
npxinit(control)
475
	u_short control;
491
	u_short control;
476
{
492
{
477
	struct save87 dummy;
493
	union savefpu dummy;
478
494
479
	if (!npx_exists)
495
	if (!npx_exists)
480
		return;
496
		return;
481
	/*
497
	/*
482
	 * fninit has the same h/w bugs as fnsave.  Use the detoxified
498
	 * fninit has the same h/w bugs as fnsave.  Use the detoxified
483
	 * fnsave to throw away any junk in the fpu.  npxsave() initializes
499
	 * fnsave to throw away any junk in the fpu.  npxsave() initializes
484
	 * the fpu and sets npxproc = NULL as important side effects.
500
	 * the fpu and sets npxproc = NULL as important side effects.
485
	 */
501
	 */
486
	npxsave(&dummy);
502
	npxsave(&dummy);
487
	stop_emulating();
503
	stop_emulating();
488
	fldcw(&control);
504
	fldcw(&control);
489
	if (curpcb != NULL)
505
	if (curpcb != NULL)
490
		fnsave(&curpcb->pcb_savefpu);
506
		fpusave(&curpcb->pcb_save);
491
	start_emulating();
507
	start_emulating();
492
}
508
}
493
509
494
/*
510
/*
495
 * Free coprocessor (if we have it).
511
 * Free coprocessor (if we have it).
496
 */
512
 */
497
void
513
void
498
npxexit(p)
514
npxexit(p)
499
	struct proc *p;
515
	struct proc *p;
500
{
516
{
501
517
502
	if (p == npxproc)
518
	if (p == npxproc)
503
		npxsave(&curpcb->pcb_savefpu);
519
		npxsave(&curpcb->pcb_save);
504
#ifdef NPX_DEBUG
520
#ifdef NPX_DEBUG
505
	if (npx_exists) {
521
	if (npx_exists) {
506
		u_int	masked_exceptions;
522
		u_int	masked_exceptions;
507
523
508
		masked_exceptions = curpcb->pcb_savefpu.sv_env.en_cw
524
		masked_exceptions = curpcb->pcb_savefpu.sv_env.en_cw
509
				    & curpcb->pcb_savefpu.sv_env.en_sw & 0x7f;
525
				    & curpcb->pcb_savefpu.sv_env.en_sw & 0x7f;
510
		/*
526
		/*
511
		 * Log exceptions that would have trapped with the old
527
		 * Log exceptions that would have trapped with the old
512
		 * control word (overflow, divide by 0, and invalid operand).
528
		 * control word (overflow, divide by 0, and invalid operand).
Lines 708-739 Link Here
708
 * solution for signals other than SIGFPE.
724
 * solution for signals other than SIGFPE.
709
 */
725
 */
710
void
726
void
711
npx_intr(dummy)
727
npx_intr(dummy)
712
	void *dummy;
728
	void *dummy;
713
{
729
{
714
	int code;
730
	int code;
715
	u_short control;
731
	u_short control;
716
	struct intrframe *frame;
732
	struct intrframe *frame;
733
	u_long *pstatus;
717
734
718
	if (npxproc == NULL || !npx_exists) {
735
	if (npxproc == NULL || !npx_exists) {
719
		printf("npxintr: npxproc = %p, curproc = %p, npx_exists = %d\n",
736
		printf("npxintr: npxproc = %p, curproc = %p, npx_exists = %d\n",
720
		       npxproc, curproc, npx_exists);
737
		       npxproc, curproc, npx_exists);
721
		panic("npxintr from nowhere");
738
		panic("npxintr from nowhere");
722
	}
739
	}
723
	if (npxproc != curproc) {
740
	if (npxproc != curproc) {
724
		printf("npxintr: npxproc = %p, curproc = %p, npx_exists = %d\n",
741
		printf("npxintr: npxproc = %p, curproc = %p, npx_exists = %d\n",
725
		       npxproc, curproc, npx_exists);
742
		       npxproc, curproc, npx_exists);
726
		panic("npxintr from non-current process");
743
		panic("npxintr from non-current process");
727
	}
744
	}
728
745
746
	pstatus = FPU_STATUS_EX(curpcb);
747
729
	outb(0xf0, 0);
748
	outb(0xf0, 0);
730
	fnstsw(&curpcb->pcb_savefpu.sv_ex_sw);
749
	fnstsw(pstatus);
731
	fnstcw(&control);
750
	fnstcw(&control);
732
	fnclex();
751
	fnclex();
733
752
734
	/*
753
	/*
735
	 * Pass exception to process.
754
	 * Pass exception to process.
736
	 */
755
	 */
737
	frame = (struct intrframe *)&dummy;	/* XXX */
756
	frame = (struct intrframe *)&dummy;	/* XXX */
738
	if ((ISPL(frame->if_cs) == SEL_UPL) || (frame->if_eflags & PSL_VM)) {
757
	if ((ISPL(frame->if_cs) == SEL_UPL) || (frame->if_eflags & PSL_VM)) {
739
		/*
758
		/*
Lines 747-766 Link Here
747
		 * in doreti, and the frame for that could easily be set up
766
		 * in doreti, and the frame for that could easily be set up
748
		 * just before it is used).
767
		 * just before it is used).
749
		 */
768
		 */
750
		curproc->p_md.md_regs = INTR_TO_TRAPFRAME(frame);
769
		curproc->p_md.md_regs = INTR_TO_TRAPFRAME(frame);
751
		/*
770
		/*
752
		 * Encode the appropriate code for detailed information on
771
		 * Encode the appropriate code for detailed information on
753
		 * this exception.
772
		 * this exception.
754
		 */
773
		 */
755
		code = 
774
		code = 
756
		    fpetable[(curpcb->pcb_savefpu.sv_ex_sw & ~control & 0x3f) |
775
		    fpetable[(*pstatus & ~control & 0x3f) | (*pstatus & 0x40)];
757
			(curpcb->pcb_savefpu.sv_ex_sw & 0x40)];
758
		trapsignal(curproc, SIGFPE, code);
776
		trapsignal(curproc, SIGFPE, code);
759
	} else {
777
	} else {
760
		/*
778
		/*
761
		 * Nested interrupt.  These losers occur when:
779
		 * Nested interrupt.  These losers occur when:
762
		 *	o an IRQ13 is bogusly generated at a bogus time, e.g.:
780
		 *	o an IRQ13 is bogusly generated at a bogus time, e.g.:
763
		 *		o immediately after an fnsave or frstor of an
781
		 *		o immediately after an fnsave or frstor of an
764
		 *		  error state.
782
		 *		  error state.
765
		 *		o a couple of 386 instructions after
783
		 *		o a couple of 386 instructions after
766
		 *		  "fstpl _memvar" causes a stack overflow.
784
		 *		  "fstpl _memvar" causes a stack overflow.
Lines 779-847 Link Here
779
 * Implement device not available (DNA) exception
797
 * Implement device not available (DNA) exception
780
 *
798
 *
781
 * It would be better to switch FP context here (if curproc != npxproc)
799
 * It would be better to switch FP context here (if curproc != npxproc)
782
 * and not necessarily for every context switch, but it is too hard to
800
 * and not necessarily for every context switch, but it is too hard to
783
 * access foreign pcb's.
801
 * access foreign pcb's.
784
 */
802
 */
785
int
803
int
786
npxdna()
804
npxdna()
787
{
805
{
806
	u_long *pstatus;
807
788
	if (!npx_exists)
808
	if (!npx_exists)
789
		return (0);
809
		return (0);
790
	if (npxproc != NULL) {
810
	if (npxproc != NULL) {
791
		printf("npxdna: npxproc = %p, curproc = %p\n",
811
		printf("npxdna: npxproc = %p, curproc = %p\n",
792
		       npxproc, curproc);
812
		       npxproc, curproc);
793
		panic("npxdna");
813
		panic("npxdna");
794
	}
814
	}
795
	stop_emulating();
815
	stop_emulating();
796
	/*
816
	/*
797
	 * Record new context early in case frstor causes an IRQ13.
817
	 * Record new context early in case frstor causes an IRQ13.
798
	 */
818
	 */
799
	npxproc = curproc;
819
	npxproc = curproc;
800
	curpcb->pcb_savefpu.sv_ex_sw = 0;
820
821
	pstatus = FPU_STATUS_EX(curpcb);
822
	*pstatus = 0;
823
801
	/*
824
	/*
802
	 * The following frstor may cause an IRQ13 when the state being
825
	 * The following frstor may cause an IRQ13 when the state being
803
	 * restored has a pending error.  The error will appear to have been
826
	 * restored has a pending error.  The error will appear to have been
804
	 * triggered by the current (npx) user instruction even when that
827
	 * triggered by the current (npx) user instruction even when that
805
	 * instruction is a no-wait instruction that should not trigger an
828
	 * instruction is a no-wait instruction that should not trigger an
806
	 * error (e.g., fnclex).  On at least one 486 system all of the
829
	 * error (e.g., fnclex).  On at least one 486 system all of the
807
	 * no-wait instructions are broken the same as frstor, so our
830
	 * no-wait instructions are broken the same as frstor, so our
808
	 * treatment does not amplify the breakage.  On at least one
831
	 * treatment does not amplify the breakage.  On at least one
809
	 * 386/Cyrix 387 system, fnclex works correctly while frstor and
832
	 * 386/Cyrix 387 system, fnclex works correctly while frstor and
810
	 * fnsave are broken, so our treatment breaks fnclex if it is the
833
	 * fnsave are broken, so our treatment breaks fnclex if it is the
811
	 * first FPU instruction after a context switch.
834
	 * first FPU instruction after a context switch.
812
	 */
835
	 */
813
	frstor(&curpcb->pcb_savefpu);
836
	fpurstor(&curpcb->pcb_save);
814
837
815
	return (1);
838
	return (1);
816
}
839
}
817
840
818
/*
841
/*
819
 * Wrapper for fnsave instruction to handle h/w bugs.  If there is an error
842
 * Wrapper for fnsave instruction to handle h/w bugs.  If there is an error
820
 * pending, then fnsave generates a bogus IRQ13 on some systems.  Force
843
 * pending, then fnsave generates a bogus IRQ13 on some systems.  Force
821
 * any IRQ13 to be handled immediately, and then ignore it.  This routine is
844
 * any IRQ13 to be handled immediately, and then ignore it.  This routine is
822
 * often called at splhigh so it must not use many system services.  In
845
 * often called at splhigh so it must not use many system services.  In
823
 * particular, it's much easier to install a special handler than to
846
 * particular, it's much easier to install a special handler than to
824
 * guarantee that it's safe to use npxintr() and its supporting code.
847
 * guarantee that it's safe to use npxintr() and its supporting code.
825
 */
848
 */
826
void
849
void
827
npxsave(addr)
850
npxsave(addr)
828
	struct save87 *addr;
851
	union savefpu *addr;
829
{
852
{
830
#ifdef SMP
853
#if defined(SMP) || defined(CPU_ENABLE_SSE)
831
832
	stop_emulating();
854
	stop_emulating();
833
	fnsave(addr);
855
	fpusave(addr);
834
	/* fnop(); */
856
	/* fnop(); */
835
	start_emulating();
857
	start_emulating();
836
	npxproc = NULL;
858
	npxproc = NULL;
837
859
838
#else /* SMP */
860
#else /* SMP or CPU_ENABLE_SSE */
839
861
840
	u_char	icu1_mask;
862
	u_char	icu1_mask;
841
	u_char	icu2_mask;
863
	u_char	icu2_mask;
842
	u_char	old_icu1_mask;
864
	u_char	old_icu1_mask;
843
	u_char	old_icu2_mask;
865
	u_char	old_icu2_mask;
844
	struct gate_descriptor	save_idt_npxintr;
866
	struct gate_descriptor	save_idt_npxintr;
845
867
846
	disable_intr();
868
	disable_intr();
847
	old_icu1_mask = inb(IO_ICU1 + 1);
869
	old_icu1_mask = inb(IO_ICU1 + 1);
Lines 862-879 Link Here
862
	outb(IO_ICU1 + 1,
884
	outb(IO_ICU1 + 1,
863
	     (icu1_mask & ~npx0_imask) | (old_icu1_mask & npx0_imask));
885
	     (icu1_mask & ~npx0_imask) | (old_icu1_mask & npx0_imask));
864
	outb(IO_ICU2 + 1,
886
	outb(IO_ICU2 + 1,
865
	     (icu2_mask & ~(npx0_imask >> 8))
887
	     (icu2_mask & ~(npx0_imask >> 8))
866
	     | (old_icu2_mask & (npx0_imask >> 8)));
888
	     | (old_icu2_mask & (npx0_imask >> 8)));
867
	idt[npx_intrno] = save_idt_npxintr;
889
	idt[npx_intrno] = save_idt_npxintr;
868
	enable_intr();		/* back to usual state */
890
	enable_intr();		/* back to usual state */
869
891
870
#endif /* SMP */
892
#endif /* SMP */
893
}
894
895
static void
896
fpusave(addr)
897
	union savefpu *addr;
898
{
899
#ifdef CPU_ENABLE_SSE
900
	static struct savexmm svxmm __attribute__((aligned(16)));
901
902
	if (cpu_fxsr) {
903
		fxsave(&svxmm);
904
		bcopy(&svxmm, addr, sizeof(struct savexmm));
905
		return;
906
	}
907
#endif /* CPU_ENABLE_SSE */
908
	fnsave(addr);
909
}
910
911
static void
912
fpurstor(addr)
913
	union savefpu *addr;
914
{
915
#ifdef CPU_ENABLE_SSE
916
	static struct savexmm svxmm __attribute__((aligned(16)));
917
918
	if (cpu_fxsr) {
919
		bcopy(addr, &svxmm, sizeof (struct savexmm));
920
		fxrstor(&svxmm);
921
		return;
922
	}
923
#endif /* CPU_ENABLE_SSE */
924
	frstor(addr);
871
}
925
}
872
926
873
#ifdef I586_CPU
927
#ifdef I586_CPU
874
static long
928
static long
875
timezero(funcname, func)
929
timezero(funcname, func)
876
	const char *funcname;
930
	const char *funcname;
877
	void (*func) __P((void *buf, size_t len));
931
	void (*func) __P((void *buf, size_t len));
878
932
879
{
933
{

Return to bug 24219