1122940Speter/*-
240003Skato * Copyright (c) KATO Takenori, 1997, 1998.
324113Skato *
424113Skato * All rights reserved.  Unpublished rights reserved under the copyright
524113Skato * laws of Japan.
624113Skato *
724113Skato * Redistribution and use in source and binary forms, with or without
824113Skato * modification, are permitted provided that the following conditions
924113Skato * are met:
1024113Skato *
1124113Skato * 1. Redistributions of source code must retain the above copyright
1224113Skato *    notice, this list of conditions and the following disclaimer as
1324113Skato *    the first lines of this file unmodified.
1424113Skato * 2. Redistributions in binary form must reproduce the above copyright
1524113Skato *    notice, this list of conditions and the following disclaimer in the
1624113Skato *    documentation and/or other materials provided with the distribution.
1724113Skato *
1824113Skato * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1924113Skato * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2024113Skato * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2124113Skato * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2224113Skato * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2324113Skato * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2424113Skato * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2524113Skato * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2624113Skato * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2724113Skato * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2824113Skato */
2924113Skato
30118031Sobrien#include <sys/cdefs.h>
31118031Sobrien__FBSDID("$FreeBSD$");
32118031Sobrien
3324113Skato#include "opt_cpu.h"
3424113Skato
3524113Skato#include <sys/param.h>
3624113Skato#include <sys/kernel.h>
37242433Skib#include <sys/pcpu.h>
3824113Skato#include <sys/systm.h>
3979609Speter#include <sys/sysctl.h>
4024113Skato
4124113Skato#include <machine/cputypes.h>
4224113Skato#include <machine/md_var.h>
4324113Skato#include <machine/specialreg.h>
4424113Skato
45130224Speter#include <vm/vm.h>
46130224Speter#include <vm/pmap.h>
4740003Skato
48109700Sjhbstatic int	hw_instruction_sse;
4979609SpeterSYSCTL_INT(_hw, OID_AUTO, instruction_sse, CTLFLAG_RD,
50109700Sjhb    &hw_instruction_sse, 0, "SIMD/MMX2 instructions available in CPU");
51199067Skuriyama/*
52199067Skuriyama * -1: automatic (default)
53199067Skuriyama *  0: keep enable CLFLUSH
54199067Skuriyama *  1: force disable CLFLUSH
55199067Skuriyama */
56199067Skuriyamastatic int	hw_clflush_disable = -1;
5779609Speter
58114349Speterint	cpu;			/* Are we 386, 386sx, 486, etc? */
59114349Speteru_int	cpu_feature;		/* Feature flags */
60130224Speteru_int	cpu_feature2;		/* Feature flags */
61151348Sjkimu_int	amd_feature;		/* AMD feature flags */
62151348Sjkimu_int	amd_feature2;		/* AMD feature flags */
63184101Sjkimu_int	amd_pminfo;		/* AMD advanced power management info */
64187109Sjkimu_int	via_feature_rng;	/* VIA RNG features */
65187109Sjkimu_int	via_feature_xcrypt;	/* VIA ACE features */
66114349Speteru_int	cpu_high;		/* Highest arg to CPUID */
67130224Speteru_int	cpu_exthigh;		/* Highest arg to extended CPUID */
68114349Speteru_int	cpu_id;			/* Stepping ID */
69114349Speteru_int	cpu_procinfo;		/* HyperThreading Info / Brand Index / CLFUSH */
70151348Sjkimu_int	cpu_procinfo2;		/* Multicore info */
71114349Speterchar	cpu_vendor[20];		/* CPU Origin code */
72185341Sjkimu_int	cpu_vendor_id;		/* CPU vendor ID */
73109700Sjhbu_int	cpu_fxsr;		/* SSE enabled */
74159783Sdavidxuu_int	cpu_mxcsr_mask;		/* Valid bits in mxcsr */
75195820Skibu_int	cpu_clflush_line_size = 32;
76242432Skibu_int	cpu_stdext_feature;
77230426Skibu_int	cpu_max_ext_state_size;
78253747Savgu_int	cpu_mon_mwait_flags;	/* MONITOR/MWAIT flags (CPUID.05H.ECX) */
79253747Savgu_int	cpu_mon_min_size;	/* MONITOR minimum range size, bytes */
80253747Savgu_int	cpu_mon_max_size;	/* MONITOR minimum range size, bytes */
8182261Speter
82187109SjkimSYSCTL_UINT(_hw, OID_AUTO, via_feature_rng, CTLFLAG_RD,
83220018Sjkim	&via_feature_rng, 0, "VIA RNG feature available in CPU");
84187109SjkimSYSCTL_UINT(_hw, OID_AUTO, via_feature_xcrypt, CTLFLAG_RD,
85220018Sjkim	&via_feature_xcrypt, 0, "VIA xcrypt feature available in CPU");
86187109Sjkim
87233702Sjkimstatic void
88233702Sjkiminit_amd(void)
89233702Sjkim{
90233702Sjkim
91233702Sjkim	/*
92233702Sjkim	 * Work around Erratum 721 for Family 10h and 12h processors.
93233702Sjkim	 * These processors may incorrectly update the stack pointer
94233702Sjkim	 * after a long series of push and/or near-call instructions,
95233702Sjkim	 * or a long series of pop and/or near-return instructions.
96233702Sjkim	 *
97233702Sjkim	 * http://support.amd.com/us/Processor_TechDocs/41322_10h_Rev_Gd.pdf
98233702Sjkim	 * http://support.amd.com/us/Processor_TechDocs/44739_12h_Rev_Gd.pdf
99239125Skib	 *
100239125Skib	 * Hypervisors do not provide access to the errata MSR,
101239125Skib	 * causing #GP exception on attempt to apply the errata.  The
102239125Skib	 * MSR write shall be done on host and persist globally
103239125Skib	 * anyway, so do not try to do it when under virtualization.
104233702Sjkim	 */
105233702Sjkim	switch (CPUID_TO_FAMILY(cpu_id)) {
106233702Sjkim	case 0x10:
107233702Sjkim	case 0x12:
108239125Skib		if ((cpu_feature2 & CPUID2_HV) == 0)
109239125Skib			wrmsr(0xc0011029, rdmsr(0xc0011029) | 1);
110233702Sjkim		break;
111233702Sjkim	}
112233702Sjkim}
113233702Sjkim
11424113Skato/*
115220018Sjkim * Initialize special VIA features
116187109Sjkim */
117187109Sjkimstatic void
118187109Sjkiminit_via(void)
119187109Sjkim{
120187109Sjkim	u_int regs[4], val;
121187109Sjkim
122220018Sjkim	/*
123220018Sjkim	 * Check extended CPUID for PadLock features.
124220018Sjkim	 *
125220018Sjkim	 * http://www.via.com.tw/en/downloads/whitepapers/initiatives/padlock/programming_guide.pdf
126220018Sjkim	 */
127187109Sjkim	do_cpuid(0xc0000000, regs);
128220018Sjkim	if (regs[0] >= 0xc0000001) {
129187109Sjkim		do_cpuid(0xc0000001, regs);
130187109Sjkim		val = regs[3];
131187109Sjkim	} else
132220018Sjkim		return;
133187109Sjkim
134220018Sjkim	/* Enable RNG if present. */
135220018Sjkim	if ((val & VIA_CPUID_HAS_RNG) != 0) {
136187109Sjkim		via_feature_rng = VIA_HAS_RNG;
137220018Sjkim		wrmsr(0x110B, rdmsr(0x110B) | VIA_CPUID_DO_RNG);
138187109Sjkim	}
139220018Sjkim
140220018Sjkim	/* Enable PadLock if present. */
141220018Sjkim	if ((val & VIA_CPUID_HAS_ACE) != 0)
142187109Sjkim		via_feature_xcrypt |= VIA_HAS_AES;
143220018Sjkim	if ((val & VIA_CPUID_HAS_ACE2) != 0)
144187109Sjkim		via_feature_xcrypt |= VIA_HAS_AESCTR;
145220018Sjkim	if ((val & VIA_CPUID_HAS_PHE) != 0)
146187109Sjkim		via_feature_xcrypt |= VIA_HAS_SHA;
147220018Sjkim	if ((val & VIA_CPUID_HAS_PMM) != 0)
148187109Sjkim		via_feature_xcrypt |= VIA_HAS_MM;
149220018Sjkim	if (via_feature_xcrypt != 0)
150220018Sjkim		wrmsr(0x1107, rdmsr(0x1107) | (1 << 28));
151187109Sjkim}
152187109Sjkim
153187109Sjkim/*
154130224Speter * Initialize CPU control registers
15579609Speter */
15679609Spetervoid
157130224Speterinitializecpu(void)
15879609Speter{
159130224Speter	uint64_t msr;
160242433Skib	uint32_t cr4;
161130224Speter
162242433Skib	cr4 = rcr4();
16379609Speter	if ((cpu_feature & CPUID_XMM) && (cpu_feature & CPUID_FXSR)) {
164242433Skib		cr4 |= CR4_FXSR | CR4_XMM;
16579609Speter		cpu_fxsr = hw_instruction_sse = 1;
16679609Speter	}
167242433Skib	if (cpu_stdext_feature & CPUID_STDEXT_FSGSBASE)
168242433Skib		cr4 |= CR4_FSGSBASE;
169242433Skib
170242433Skib	/*
171242433Skib	 * Postpone enabling the SMEP on the boot CPU until the page
172242433Skib	 * tables are switched from the boot loader identity mapping
173242433Skib	 * to the kernel tables.  The boot loader enables the U bit in
174242433Skib	 * its tables.
175242433Skib	 */
176242433Skib	if (!IS_BSP() && (cpu_stdext_feature & CPUID_STDEXT_SMEP))
177242433Skib		cr4 |= CR4_SMEP;
178242433Skib	load_cr4(cr4);
179130224Speter	if ((amd_feature & AMDID_NX) != 0) {
180130224Speter		msr = rdmsr(MSR_EFER) | EFER_NXE;
181130224Speter		wrmsr(MSR_EFER, msr);
182130224Speter		pg_nx = PG_NX;
18324113Skato	}
184233702Sjkim	switch (cpu_vendor_id) {
185233702Sjkim	case CPU_VENDOR_AMD:
186233702Sjkim		init_amd();
187233702Sjkim		break;
188233702Sjkim	case CPU_VENDOR_CENTAUR:
189187109Sjkim		init_via();
190233702Sjkim		break;
191233702Sjkim	}
192199253Skib}
193195820Skib
194199253Skibvoid
195254374Sbrooksinitializecpucache(void)
196199253Skib{
197199253Skib
198195820Skib	/*
199195820Skib	 * CPUID with %eax = 1, %ebx returns
200195820Skib	 * Bits 15-8: CLFLUSH line size
201195820Skib	 * 	(Value * 8 = cache line size in bytes)
202195820Skib	 */
203195820Skib	if ((cpu_feature & CPUID_CLFSH) != 0)
204195820Skib		cpu_clflush_line_size = ((cpu_procinfo >> 8) & 0xff) * 8;
205197663Skib	/*
206210774Sjhb	 * XXXKIB: (temporary) hack to work around traps generated
207210774Sjhb	 * when CLFLUSHing APIC register window under virtualization
208210774Sjhb	 * environments.  These environments tend to disable the
209210774Sjhb	 * CPUID_SS feature even though the native CPU supports it.
210197663Skib	 */
211199067Skuriyama	TUNABLE_INT_FETCH("hw.clflush_disable", &hw_clflush_disable);
212210774Sjhb	if (vm_guest != VM_GUEST_NO && hw_clflush_disable == -1)
213197663Skib		cpu_feature &= ~CPUID_CLFSH;
214199067Skuriyama	/*
215199067Skuriyama	 * Allow to disable CLFLUSH feature manually by
216210774Sjhb	 * hw.clflush_disable tunable.
217199067Skuriyama	 */
218199215Skuriyama	if (hw_clflush_disable == 1)
219199067Skuriyama		cpu_feature &= ~CPUID_CLFSH;
22024113Skato}
221