source: mainline/kernel/arch/ia32/src/cpu/cpu.c

Last change on this file was f3dbe27, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 2 years ago

Reduce locking further with lazy FPU

It turns out we only need a lock to synchronize between the trap
handler and thread destructor. The atomic operations introduced
are just plain reads and writes, written in an ugly fashion to
appease C11 undefined behavior gods.

In principle we could get rid of that if we made cpu_t::fpu_owner
a strong reference, but that would mean a thread structure could
be held in limbo indefinitely if a new thread is not being
scheduled or doesn't use FPU.

  • Property mode set to 100644
File size: 3.9 KB
Line 
1/*
2 * Copyright (c) 2001-2004 Jakub Jermar
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup kernel_ia32
30 * @{
31 */
32/** @file
33 */
34
35#include <arch/cpu.h>
36#include <arch/cpuid.h>
37#include <arch/pm.h>
38
39#include <arch.h>
40#include <stdint.h>
41#include <stdio.h>
42#include <fpu_context.h>
43
44#include <arch/smp/apic.h>
45#include <arch/syscall.h>
46
47/*
48 * Identification of CPUs.
49 * Contains only non-MP-Specification specific SMP code.
50 */
51#define AMD_CPUID_EBX UINT32_C(0x68747541)
52#define AMD_CPUID_ECX UINT32_C(0x444d4163)
53#define AMD_CPUID_EDX UINT32_C(0x69746e65)
54
55#define INTEL_CPUID_EBX UINT32_C(0x756e6547)
56#define INTEL_CPUID_ECX UINT32_C(0x6c65746e)
57#define INTEL_CPUID_EDX UINT32_C(0x49656e69)
58
59enum vendor {
60 VendorUnknown = 0,
61 VendorAMD,
62 VendorIntel
63};
64
65static const char *vendor_str[] = {
66 "Unknown Vendor",
67 "AMD",
68 "Intel"
69};
70
71void fpu_disable(void)
72{
73 write_cr0(read_cr0() | CR0_TS);
74}
75
76void fpu_enable(void)
77{
78 write_cr0(read_cr0() & ~CR0_TS);
79}
80
81void cpu_arch_init(void)
82{
83 cpu_info_t info;
84 uint32_t help = 0;
85
86 CPU->arch.tss = tss_p;
87 CPU->arch.tss->iomap_base = &CPU->arch.tss->iomap[0] - ((uint8_t *) CPU->arch.tss);
88
89 cpuid(INTEL_CPUID_STANDARD, &info);
90
91 CPU->arch.fi.word = info.cpuid_edx;
92
93 if (CPU->arch.fi.bits.fxsr)
94 fpu_fxsr();
95 else
96 fpu_fsr();
97
98 if (CPU->arch.fi.bits.sse) {
99 asm volatile (
100 "mov %%cr4, %[help]\n"
101 "or %[mask], %[help]\n"
102 "mov %[help], %%cr4\n"
103 : [help] "+r" (help)
104 : [mask] "i" (CR4_OSFXSR | CR4_OSXMMEXCPT)
105 );
106 }
107
108#ifndef PROCESSOR_i486
109 if (CPU->arch.fi.bits.sep) {
110 /* Setup fast SYSENTER/SYSEXIT syscalls */
111 syscall_setup_cpu();
112 }
113#endif
114}
115
116void cpu_identify(void)
117{
118 cpu_info_t info;
119
120 CPU->arch.vendor = VendorUnknown;
121 if (has_cpuid()) {
122 cpuid(INTEL_CPUID_LEVEL, &info);
123
124 /*
125 * Check for AMD processor.
126 */
127 if ((info.cpuid_ebx == AMD_CPUID_EBX) &&
128 (info.cpuid_ecx == AMD_CPUID_ECX) &&
129 (info.cpuid_edx == AMD_CPUID_EDX))
130 CPU->arch.vendor = VendorAMD;
131
132 /*
133 * Check for Intel processor.
134 */
135 if ((info.cpuid_ebx == INTEL_CPUID_EBX) &&
136 (info.cpuid_ecx == INTEL_CPUID_ECX) &&
137 (info.cpuid_edx == INTEL_CPUID_EDX))
138 CPU->arch.vendor = VendorIntel;
139
140 cpuid(INTEL_CPUID_STANDARD, &info);
141 CPU->arch.family = (info.cpuid_eax >> 8) & 0x0fU;
142 CPU->arch.model = (info.cpuid_eax >> 4) & 0x0fU;
143 CPU->arch.stepping = (info.cpuid_eax >> 0) & 0x0fU;
144 }
145}
146
147void cpu_print_report(cpu_t *cpu)
148{
149 printf("cpu%u: (%s family=%u model=%u stepping=%u apicid=%u) %" PRIu16
150 " MHz\n", cpu->id, vendor_str[cpu->arch.vendor], cpu->arch.family,
151 cpu->arch.model, cpu->arch.stepping, cpu->arch.id, cpu->frequency_mhz);
152}
153
154/** @}
155 */
Note: See TracBrowser for help on using the repository browser.