clflush.diff
| b/sys/boot/pc32/libi386/Makefile | ||
|---|---|---|
| 11 | 11 |
comconsole.c devicename.c elf32_freebsd.c \ |
| 12 | 12 |
elf64_freebsd.c gatea20.c \ |
| 13 | 13 |
i386_copy.c i386_module.c nullconsole.c pxe.c pxetramp.s \ |
| 14 |
time.c vidconsole.c x86_64_tramp.S |
|
| 14 |
smbios.c time.c vidconsole.c x86_64_tramp.S
|
|
| 15 | 15 | |
| 16 | 16 |
CFLAGS+= -ffreestanding |
| 17 | 17 |
BOOT_COMCONSOLE_PORT?= 0x3f8 |
| ... | ... | |
| 25 | 25 |
CFLAGS+= -DDISK_DEBUG |
| 26 | 26 |
.endif |
| 27 | 27 | |
| 28 |
.if !defined(BOOT_HIDE_SERIAL_NUMBERS) |
|
| 29 |
# Export serial numbers, UUID, and asset tag from loader. |
|
| 30 |
CFLAGS+= -DSMBIOS_SERIAL_NUMBERS |
|
| 31 |
.if defined(BOOT_LITTLE_ENDIAN_UUID) |
|
| 32 |
# Use little-endian UUID format as defined in SMBIOS 2.6. |
|
| 33 |
CFLAGS+= -DSMBIOS_LITTLE_ENDIAN_UUID |
|
| 34 |
.endif |
|
| 35 |
.endif |
|
| 36 | ||
| 28 | 37 |
# Include simple terminal emulation (cons25-compatible) |
| 29 | 38 |
CFLAGS+= -DTERM_EMU |
| 30 | 39 | |
| b/sys/boot/pc32/libi386/libi386.h | ||
|---|---|---|
| 96 | 96 | |
| 97 | 97 |
void biosacpi_detect(void); |
| 98 | 98 | |
| 99 |
void smbios_detect(void); |
|
| 100 | ||
| 99 | 101 |
void gateA20(void); |
| 100 | 102 | |
| 101 | 103 |
int i386_autoload(void); |
| b/sys/boot/pc32/libi386/smbios.c | ||
|---|---|---|
| 1 |
/*- |
|
| 2 |
* Copyright (c) 2005-2009 Jung-uk Kim <jkim@FreeBSD.org> |
|
| 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 |
* 1. Redistributions of source code must retain the above copyright |
|
| 9 |
* notice, this list of conditions and the following disclaimer. |
|
| 10 |
* 2. Redistributions in binary form must reproduce the above copyright |
|
| 11 |
* notice, this list of conditions and the following disclaimer in the |
|
| 12 |
* documentation and/or other materials provided with the distribution. |
|
| 13 |
* |
|
| 14 |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
|
| 15 |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
| 16 |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
| 17 |
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
|
| 18 |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
|
| 19 |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
|
| 20 |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
|
| 21 |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|
| 22 |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
|
| 23 |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
|
| 24 |
* SUCH DAMAGE. |
|
| 25 |
* |
|
| 26 |
* __FBSDID("$FreeBSD: stable/9/sys/boot/i386/libi386/smbios.c 190814 2009-04-07 17:58:15Z jkim $");
|
|
| 27 |
*/ |
|
| 28 | ||
| 29 |
#include <sys/cdefs.h> |
|
| 30 | ||
| 31 |
#include <stand.h> |
|
| 32 |
#include <bootstrap.h> |
|
| 33 |
#include <sys/param.h> |
|
| 34 |
#include <sys/endian.h> |
|
| 35 | ||
| 36 |
#include "btxv86.h" |
|
| 37 |
#include "libi386.h" |
|
| 38 | ||
| 39 |
/* |
|
| 40 |
* Detect SMBIOS and export information about the SMBIOS into the |
|
| 41 |
* environment. |
|
| 42 |
* |
|
| 43 |
* System Management BIOS Reference Specification, v2.6 Final |
|
| 44 |
* http://www.dmtf.org/standards/published_documents/DSP0134_2.6.0.pdf |
|
| 45 |
*/ |
|
| 46 | ||
| 47 |
/* |
|
| 48 |
* 2.1.1 SMBIOS Structure Table Entry Point |
|
| 49 |
* |
|
| 50 |
* "On non-EFI systems, the SMBIOS Entry Point structure, described below, can |
|
| 51 |
* be located by application software by searching for the anchor-string on |
|
| 52 |
* paragraph (16-byte) boundaries within the physical memory address range |
|
| 53 |
* 000F0000h to 000FFFFFh. This entry point encapsulates an intermediate anchor |
|
| 54 |
* string that is used by some existing DMI browsers." |
|
| 55 |
*/ |
|
| 56 |
#define SMBIOS_START 0xf0000 |
|
| 57 |
#define SMBIOS_LENGTH 0x10000 |
|
| 58 |
#define SMBIOS_STEP 0x10 |
|
| 59 |
#define SMBIOS_SIG "_SM_" |
|
| 60 |
#define SMBIOS_DMI_SIG "_DMI_" |
|
| 61 | ||
| 62 |
#define SMBIOS_GET8(base, off) (*(uint8_t *)((base) + (off))) |
|
| 63 |
#define SMBIOS_GET16(base, off) (*(uint16_t *)((base) + (off))) |
|
| 64 |
#define SMBIOS_GET32(base, off) (*(uint32_t *)((base) + (off))) |
|
| 65 | ||
| 66 |
#define SMBIOS_GETLEN(base) SMBIOS_GET8(base, 0x01) |
|
| 67 |
#define SMBIOS_GETSTR(base) ((base) + SMBIOS_GETLEN(base)) |
|
| 68 | ||
| 69 |
static uint32_t smbios_enabled_memory = 0; |
|
| 70 |
static uint32_t smbios_old_enabled_memory = 0; |
|
| 71 |
static uint8_t smbios_enabled_sockets = 0; |
|
| 72 |
static uint8_t smbios_populated_sockets = 0; |
|
| 73 | ||
| 74 |
static uint8_t |
|
| 75 |
smbios_checksum(const caddr_t addr, const uint8_t len) |
|
| 76 |
{
|
|
| 77 |
uint8_t sum; |
|
| 78 |
int i; |
|
| 79 | ||
| 80 |
for (sum = 0, i = 0; i < len; i++) |
|
| 81 |
sum += SMBIOS_GET8(addr, i); |
|
| 82 |
return (sum); |
|
| 83 |
} |
|
| 84 | ||
| 85 |
static caddr_t |
|
| 86 |
smbios_sigsearch(const caddr_t addr, const uint32_t len) |
|
| 87 |
{
|
|
| 88 |
caddr_t cp; |
|
| 89 | ||
| 90 |
/* Search on 16-byte boundaries. */ |
|
| 91 |
for (cp = addr; cp < addr + len; cp += SMBIOS_STEP) |
|
| 92 |
if (strncmp(cp, SMBIOS_SIG, 4) == 0 && |
|
| 93 |
smbios_checksum(cp, SMBIOS_GET8(cp, 0x05)) == 0 && |
|
| 94 |
strncmp(cp + 0x10, SMBIOS_DMI_SIG, 5) == 0 && |
|
| 95 |
smbios_checksum(cp + 0x10, 0x0f) == 0) |
|
| 96 |
return (cp); |
|
| 97 |
return (NULL); |
|
| 98 |
} |
|
| 99 | ||
| 100 |
static void |
|
| 101 |
smbios_setenv(const char *name, caddr_t addr, const int offset) |
|
| 102 |
{
|
|
| 103 |
caddr_t cp; |
|
| 104 |
int i, idx; |
|
| 105 | ||
| 106 |
idx = SMBIOS_GET8(addr, offset); |
|
| 107 |
if (idx != 0) {
|
|
| 108 |
cp = SMBIOS_GETSTR(addr); |
|
| 109 |
for (i = 1; i < idx; i++) |
|
| 110 |
cp += strlen(cp) + 1; |
|
| 111 |
setenv(name, cp, 1); |
|
| 112 |
} |
|
| 113 |
} |
|
| 114 | ||
| 115 |
#ifdef SMBIOS_SERIAL_NUMBERS |
|
| 116 | ||
| 117 |
#define UUID_SIZE 16 |
|
| 118 |
#define UUID_TYPE uint32_t |
|
| 119 |
#define UUID_STEP sizeof(UUID_TYPE) |
|
| 120 |
#define UUID_ALL_BITS (UUID_SIZE / UUID_STEP) |
|
| 121 |
#define UUID_GET(base, off) (*(UUID_TYPE *)((base) + (off))) |
|
| 122 | ||
| 123 |
static void |
|
| 124 |
smbios_setuuid(const char *name, const caddr_t addr, const int ver) |
|
| 125 |
{
|
|
| 126 |
char uuid[37]; |
|
| 127 |
int i, ones, zeros; |
|
| 128 |
UUID_TYPE n; |
|
| 129 |
uint32_t f1; |
|
| 130 |
uint16_t f2, f3; |
|
| 131 | ||
| 132 |
for (i = 0, ones = 0, zeros = 0; i < UUID_SIZE; i += UUID_STEP) {
|
|
| 133 |
n = UUID_GET(addr, i) + 1; |
|
| 134 |
if (zeros == 0 && n == 0) |
|
| 135 |
ones++; |
|
| 136 |
else if (ones == 0 && n == 1) |
|
| 137 |
zeros++; |
|
| 138 |
else |
|
| 139 |
break; |
|
| 140 |
} |
|
| 141 | ||
| 142 |
if (ones != UUID_ALL_BITS && zeros != UUID_ALL_BITS) {
|
|
| 143 |
/* |
|
| 144 |
* 3.3.2.1 System UUID |
|
| 145 |
* |
|
| 146 |
* "Although RFC 4122 recommends network byte order for all |
|
| 147 |
* fields, the PC industry (including the ACPI, UEFI, and |
|
| 148 |
* Microsoft specifications) has consistently used |
|
| 149 |
* little-endian byte encoding for the first three fields: |
|
| 150 |
* time_low, time_mid, time_hi_and_version. The same encoding, |
|
| 151 |
* also known as wire format, should also be used for the |
|
| 152 |
* SMBIOS representation of the UUID." |
|
| 153 |
* |
|
| 154 |
* Note: We use network byte order for backward compatibility |
|
| 155 |
* unless SMBIOS version is 2.6+ or little-endian is forced. |
|
| 156 |
*/ |
|
| 157 |
#ifndef SMBIOS_LITTLE_ENDIAN_UUID |
|
| 158 |
if (ver < 0x0206) {
|
|
| 159 |
f1 = ntohl(SMBIOS_GET32(addr, 0)); |
|
| 160 |
f2 = ntohs(SMBIOS_GET16(addr, 4)); |
|
| 161 |
f3 = ntohs(SMBIOS_GET16(addr, 6)); |
|
| 162 |
} else |
|
| 163 |
#endif |
|
| 164 |
{
|
|
| 165 |
f1 = le32toh(SMBIOS_GET32(addr, 0)); |
|
| 166 |
f2 = le16toh(SMBIOS_GET16(addr, 4)); |
|
| 167 |
f3 = le16toh(SMBIOS_GET16(addr, 6)); |
|
| 168 |
} |
|
| 169 |
sprintf(uuid, |
|
| 170 |
"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", |
|
| 171 |
f1, f2, f3, SMBIOS_GET8(addr, 8), SMBIOS_GET8(addr, 9), |
|
| 172 |
SMBIOS_GET8(addr, 10), SMBIOS_GET8(addr, 11), |
|
| 173 |
SMBIOS_GET8(addr, 12), SMBIOS_GET8(addr, 13), |
|
| 174 |
SMBIOS_GET8(addr, 14), SMBIOS_GET8(addr, 15)); |
|
| 175 |
setenv(name, uuid, 1); |
|
| 176 |
} |
|
| 177 |
} |
|
| 178 | ||
| 179 |
#undef UUID_SIZE |
|
| 180 |
#undef UUID_TYPE |
|
| 181 |
#undef UUID_STEP |
|
| 182 |
#undef UUID_ALL_BITS |
|
| 183 |
#undef UUID_GET |
|
| 184 | ||
| 185 |
#endif |
|
| 186 | ||
| 187 |
static caddr_t |
|
| 188 |
smbios_parse_table(const caddr_t addr, const int ver) |
|
| 189 |
{
|
|
| 190 |
caddr_t cp; |
|
| 191 |
int proc, size, osize, type; |
|
| 192 | ||
| 193 |
type = SMBIOS_GET8(addr, 0); /* 3.1.2 Structure Header Format */ |
|
| 194 |
switch(type) {
|
|
| 195 |
case 0: /* 3.3.1 BIOS Information (Type 0) */ |
|
| 196 |
smbios_setenv("smbios.bios.vendor", addr, 0x04);
|
|
| 197 |
smbios_setenv("smbios.bios.version", addr, 0x05);
|
|
| 198 |
smbios_setenv("smbios.bios.reldate", addr, 0x08);
|
|
| 199 |
break; |
|
| 200 | ||
| 201 |
case 1: /* 3.3.2 System Information (Type 1) */ |
|
| 202 |
smbios_setenv("smbios.system.maker", addr, 0x04);
|
|
| 203 |
smbios_setenv("smbios.system.product", addr, 0x05);
|
|
| 204 |
smbios_setenv("smbios.system.version", addr, 0x06);
|
|
| 205 |
#ifdef SMBIOS_SERIAL_NUMBERS |
|
| 206 |
smbios_setenv("smbios.system.serial", addr, 0x07);
|
|
| 207 |
smbios_setuuid("smbios.system.uuid", addr + 0x08, ver);
|
|
| 208 |
#endif |
|
| 209 |
break; |
|
| 210 | ||
| 211 |
case 2: /* 3.3.3 Base Board (or Module) Information (Type 2) */ |
|
| 212 |
smbios_setenv("smbios.planar.maker", addr, 0x04);
|
|
| 213 |
smbios_setenv("smbios.planar.product", addr, 0x05);
|
|
| 214 |
smbios_setenv("smbios.planar.version", addr, 0x06);
|
|
| 215 |
#ifdef SMBIOS_SERIAL_NUMBERS |
|
| 216 |
smbios_setenv("smbios.planar.serial", addr, 0x07);
|
|
| 217 |
#endif |
|
| 218 |
break; |
|
| 219 | ||
| 220 |
case 3: /* 3.3.4 System Enclosure or Chassis (Type 3) */ |
|
| 221 |
smbios_setenv("smbios.chassis.maker", addr, 0x04);
|
|
| 222 |
smbios_setenv("smbios.chassis.version", addr, 0x06);
|
|
| 223 |
#ifdef SMBIOS_SERIAL_NUMBERS |
|
| 224 |
smbios_setenv("smbios.chassis.serial", addr, 0x07);
|
|
| 225 |
smbios_setenv("smbios.chassis.tag", addr, 0x08);
|
|
| 226 |
#endif |
|
| 227 |
break; |
|
| 228 | ||
| 229 |
case 4: /* 3.3.5 Processor Information (Type 4) */ |
|
| 230 |
/* |
|
| 231 |
* Offset 18h: Processor Status |
|
| 232 |
* |
|
| 233 |
* Bit 7 Reserved, must be 0 |
|
| 234 |
* Bit 6 CPU Socket Populated |
|
| 235 |
* 1 - CPU Socket Populated |
|
| 236 |
* 0 - CPU Socket Unpopulated |
|
| 237 |
* Bit 5:3 Reserved, must be zero |
|
| 238 |
* Bit 2:0 CPU Status |
|
| 239 |
* 0h - Unknown |
|
| 240 |
* 1h - CPU Enabled |
|
| 241 |
* 2h - CPU Disabled by User via BIOS Setup |
|
| 242 |
* 3h - CPU Disabled by BIOS (POST Error) |
|
| 243 |
* 4h - CPU is Idle, waiting to be enabled |
|
| 244 |
* 5-6h - Reserved |
|
| 245 |
* 7h - Other |
|
| 246 |
*/ |
|
| 247 |
proc = SMBIOS_GET8(addr, 0x18); |
|
| 248 |
if ((proc & 0x07) == 1) |
|
| 249 |
smbios_enabled_sockets++; |
|
| 250 |
if ((proc & 0x40) != 0) |
|
| 251 |
smbios_populated_sockets++; |
|
| 252 |
break; |
|
| 253 | ||
| 254 |
case 6: /* 3.3.7 Memory Module Information (Type 6, Obsolete) */ |
|
| 255 |
/* |
|
| 256 |
* Offset 0Ah: Enabled Size |
|
| 257 |
* |
|
| 258 |
* Bit 7 Bank connection |
|
| 259 |
* 1 - Double-bank connection |
|
| 260 |
* 0 - Single-bank connection |
|
| 261 |
* Bit 6:0 Size (n), where 2**n is the size in MB |
|
| 262 |
* 7Dh - Not determinable (Installed Size only) |
|
| 263 |
* 7Eh - Module is installed, but no memory |
|
| 264 |
* has been enabled |
|
| 265 |
* 7Fh - Not installed |
|
| 266 |
*/ |
|
| 267 |
osize = SMBIOS_GET8(addr, 0x0a) & 0x7f; |
|
| 268 |
if (osize > 0 && osize < 22) |
|
| 269 |
smbios_old_enabled_memory += 1 << (osize + 10); |
|
| 270 |
break; |
|
| 271 | ||
| 272 |
case 17: /* 3.3.18 Memory Device (Type 17) */ |
|
| 273 |
/* |
|
| 274 |
* Offset 0Ch: Size |
|
| 275 |
* |
|
| 276 |
* Bit 15 Granularity |
|
| 277 |
* 1 - Value is in kilobytes units |
|
| 278 |
* 0 - Value is in megabytes units |
|
| 279 |
* Bit 14:0 Size |
|
| 280 |
*/ |
|
| 281 |
size = SMBIOS_GET16(addr, 0x0c); |
|
| 282 |
if (size != 0 && size != 0xffff) |
|
| 283 |
smbios_enabled_memory += (size & 0x8000) != 0 ? |
|
| 284 |
(size & 0x7fff) : (size << 10); |
|
| 285 |
break; |
|
| 286 | ||
| 287 |
default: /* skip other types */ |
|
| 288 |
break; |
|
| 289 |
} |
|
| 290 | ||
| 291 |
/* Find structure terminator. */ |
|
| 292 |
cp = SMBIOS_GETSTR(addr); |
|
| 293 |
while (SMBIOS_GET16(cp, 0) != 0) |
|
| 294 |
cp++; |
|
| 295 | ||
| 296 |
return (cp + 2); |
|
| 297 |
} |
|
| 298 | ||
| 299 |
void |
|
| 300 |
smbios_detect(void) |
|
| 301 |
{
|
|
| 302 |
char buf[16]; |
|
| 303 |
caddr_t addr, dmi, smbios; |
|
| 304 |
size_t count, length; |
|
| 305 |
uint32_t paddr; |
|
| 306 |
int i, major, minor, ver; |
|
| 307 | ||
| 308 |
/* Search signatures and validate checksums. */ |
|
| 309 |
smbios = smbios_sigsearch(PTOV(SMBIOS_START), SMBIOS_LENGTH); |
|
| 310 |
if (smbios == NULL) |
|
| 311 |
return; |
|
| 312 | ||
| 313 |
length = SMBIOS_GET16(smbios, 0x16); /* Structure Table Length */ |
|
| 314 |
paddr = SMBIOS_GET32(smbios, 0x18); /* Structure Table Address */ |
|
| 315 |
count = SMBIOS_GET16(smbios, 0x1c); /* No of SMBIOS Structures */ |
|
| 316 |
ver = SMBIOS_GET8(smbios, 0x1e); /* SMBIOS BCD Revision */ |
|
| 317 | ||
| 318 |
if (ver != 0) {
|
|
| 319 |
major = ver >> 4; |
|
| 320 |
minor = ver & 0x0f; |
|
| 321 |
if (major > 9 || minor > 9) |
|
| 322 |
ver = 0; |
|
| 323 |
} |
|
| 324 |
if (ver == 0) {
|
|
| 325 |
major = SMBIOS_GET8(smbios, 0x06); /* SMBIOS Major Version */ |
|
| 326 |
minor = SMBIOS_GET8(smbios, 0x07); /* SMBIOS Minor Version */ |
|
| 327 |
} |
|
| 328 |
ver = (major << 8) | minor; |
|
| 329 | ||
| 330 |
addr = PTOV(paddr); |
|
| 331 |
for (dmi = addr, i = 0; dmi < addr + length && i < count; i++) |
|
| 332 |
dmi = smbios_parse_table(dmi, ver); |
|
| 333 | ||
| 334 |
sprintf(buf, "%d.%d", major, minor); |
|
| 335 |
setenv("smbios.version", buf, 1);
|
|
| 336 |
if (smbios_enabled_memory > 0 || smbios_old_enabled_memory > 0) {
|
|
| 337 |
sprintf(buf, "%u", smbios_enabled_memory > 0 ? |
|
| 338 |
smbios_enabled_memory : smbios_old_enabled_memory); |
|
| 339 |
setenv("smbios.memory.enabled", buf, 1);
|
|
| 340 |
} |
|
| 341 |
if (smbios_enabled_sockets > 0) {
|
|
| 342 |
sprintf(buf, "%u", smbios_enabled_sockets); |
|
| 343 |
setenv("smbios.socket.enabled", buf, 1);
|
|
| 344 |
} |
|
| 345 |
if (smbios_populated_sockets > 0) {
|
|
| 346 |
sprintf(buf, "%u", smbios_populated_sockets); |
|
| 347 |
setenv("smbios.socket.populated", buf, 1);
|
|
| 348 |
} |
|
| 349 |
} |
|
| b/sys/boot/pc32/loader/main.c | ||
|---|---|---|
| 240 | 240 |
/* detect ACPI for future reference */ |
| 241 | 241 |
biosacpi_detect(); |
| 242 | 242 | |
| 243 |
/* detect SMBIOS for future reference */ |
|
| 244 |
smbios_detect(); |
|
| 245 | ||
| 243 | 246 |
/* enable EHCI */ |
| 244 | 247 |
setenv("ehci_load", "YES", 1);
|
| 245 | 248 | |
| b/sys/cpu/i386/include/cpufunc.h | ||
|---|---|---|
| 113 | 113 |
return (result); |
| 114 | 114 |
} |
| 115 | 115 | |
| 116 |
static __inline void |
|
| 117 |
clflush(u_long addr) |
|
| 118 |
{
|
|
| 119 | ||
| 120 |
__asm __volatile("clflush %0" : : "m" (*(char *)addr));
|
|
| 121 |
} |
|
| 122 | ||
| 116 | 123 |
/* |
| 117 | 124 |
* Test and set the specified bit (1 << bit) in the integer. The |
| 118 | 125 |
* previous value of the bit is returned (0 or 1). |
| b/sys/cpu/x86_64/include/cpufunc.h | ||
|---|---|---|
| 125 | 125 |
} |
| 126 | 126 | |
| 127 | 127 |
static __inline void |
| 128 |
clflush(u_long addr) |
|
| 129 |
{
|
|
| 130 | ||
| 131 |
__asm __volatile("clflush %0" : : "m" (*(char *)addr));
|
|
| 132 |
} |
|
| 133 | ||
| 134 |
static __inline void |
|
| 128 | 135 |
do_cpuid(u_int ax, u_int *p) |
| 129 | 136 |
{
|
| 130 | 137 |
__asm __volatile("cpuid"
|
| b/sys/kern/subr_param.c | ||
|---|---|---|
| 46 | 46 |
#include <sys/param.h> |
| 47 | 47 |
#include <sys/systm.h> |
| 48 | 48 |
#include <sys/kernel.h> |
| 49 |
#include <sys/sysctl.h> |
|
| 49 | 50 |
#include <sys/malloc.h> |
| 50 | 51 |
#include <vm/pmap.h> |
| 51 | 52 |
#include <machine/vmparam.h> |
| ... | ... | |
| 56 | 57 | |
| 57 | 58 |
#ifndef HZ |
| 58 | 59 |
#define HZ 100 |
| 60 |
# ifndef HZ_VM |
|
| 61 |
# define HZ_VM 100 |
|
| 62 |
# endif |
|
| 63 |
#else |
|
| 64 |
# ifndef HZ_VM |
|
| 65 |
# define HZ_VM HZ |
|
| 66 |
# endif |
|
| 59 | 67 |
#endif |
| 60 | 68 |
#define NPROC (20 + 16 * maxusers) |
| 61 | 69 |
#ifndef NBUF |
| ... | ... | |
| 68 | 76 |
#define MAXPOSIXLOCKSPERUID (maxusers * 64) /* Should be a safe value */ |
| 69 | 77 |
#endif |
| 70 | 78 | |
| 79 |
static int sysctl_kern_vm_guest(SYSCTL_HANDLER_ARGS); |
|
| 80 | ||
| 71 | 81 |
int hz; |
| 72 | 82 |
int stathz; |
| 73 | 83 |
int profhz; |
| ... | ... | |
| 88 | 98 |
int nswbuf; |
| 89 | 99 |
long maxswzone; /* max swmeta KVA storage */ |
| 90 | 100 |
long maxbcache; /* max buffer cache KVA storage */ |
| 101 |
int vm_guest; /* Running as virtual machine guest? */ |
|
| 91 | 102 |
u_quad_t maxtsiz; /* max text size */ |
| 92 | 103 |
u_quad_t dfldsiz; /* initial data size limit */ |
| 93 | 104 |
u_quad_t maxdsiz; /* max data size */ |
| ... | ... | |
| 95 | 106 |
u_quad_t maxssiz; /* max stack size */ |
| 96 | 107 |
u_quad_t sgrowsiz; /* amount to grow stack */ |
| 97 | 108 | |
| 109 |
SYSCTL_PROC(_kern, OID_AUTO, vm_guest, CTLFLAG_RD | CTLTYPE_STRING, |
|
| 110 |
NULL, 0, sysctl_kern_vm_guest, "A", |
|
| 111 |
"Virtual machine guest detected? (none|generic|xen)"); |
|
| 112 | ||
| 98 | 113 |
/* |
| 99 | 114 |
* These have to be allocated somewhere; allocating |
| 100 | 115 |
* them here forces loader errors if this file is omitted |
| ... | ... | |
| 103 | 118 |
struct buf *swbuf; |
| 104 | 119 | |
| 105 | 120 |
/* |
| 121 |
* The elements of this array are ordered based upon the values of the |
|
| 122 |
* corresponding enum VM_GUEST members. |
|
| 123 |
*/ |
|
| 124 |
static const char *const vm_guest_sysctl_names[] = {
|
|
| 125 |
"none", |
|
| 126 |
"generic", |
|
| 127 |
"xen", |
|
| 128 |
NULL |
|
| 129 |
}; |
|
| 130 | ||
| 131 |
#ifndef XEN |
|
| 132 |
static const char *const vm_bnames[] = {
|
|
| 133 |
"QEMU", /* QEMU */ |
|
| 134 |
"Plex86", /* Plex86 */ |
|
| 135 |
"Bochs", /* Bochs */ |
|
| 136 |
"Xen", /* Xen */ |
|
| 137 |
NULL |
|
| 138 |
}; |
|
| 139 | ||
| 140 |
static const char *const vm_pnames[] = {
|
|
| 141 |
"VMware Virtual Platform", /* VMWare VM */ |
|
| 142 |
"Virtual Machine", /* Microsoft VirtualPC */ |
|
| 143 |
"VirtualBox", /* Sun xVM VirtualBox */ |
|
| 144 |
"Parallels Virtual Platform", /* Parallels VM */ |
|
| 145 |
NULL |
|
| 146 |
}; |
|
| 147 | ||
| 148 | ||
| 149 |
/* |
|
| 150 |
* Detect known Virtual Machine hosts by inspecting the emulated BIOS. |
|
| 151 |
*/ |
|
| 152 |
static enum VM_GUEST |
|
| 153 |
detect_virtual(void) |
|
| 154 |
{
|
|
| 155 |
char *sysenv; |
|
| 156 |
int i; |
|
| 157 | ||
| 158 |
sysenv = kgetenv("smbios.bios.vendor");
|
|
| 159 |
if (sysenv != NULL) {
|
|
| 160 |
for (i = 0; vm_bnames[i] != NULL; i++) |
|
| 161 |
if (strcmp(sysenv, vm_bnames[i]) == 0) {
|
|
| 162 |
kfreeenv(sysenv); |
|
| 163 |
return (VM_GUEST_VM); |
|
| 164 |
} |
|
| 165 |
kfreeenv(sysenv); |
|
| 166 |
} |
|
| 167 |
sysenv = kgetenv("smbios.system.product");
|
|
| 168 |
if (sysenv != NULL) {
|
|
| 169 |
for (i = 0; vm_pnames[i] != NULL; i++) |
|
| 170 |
if (strcmp(sysenv, vm_pnames[i]) == 0) {
|
|
| 171 |
kfreeenv(sysenv); |
|
| 172 |
return (VM_GUEST_VM); |
|
| 173 |
} |
|
| 174 |
kfreeenv(sysenv); |
|
| 175 |
} |
|
| 176 |
return (VM_GUEST_NO); |
|
| 177 |
} |
|
| 178 |
#endif |
|
| 179 | ||
| 180 |
/* |
|
| 106 | 181 |
* Boot time overrides that are not scaled against main memory |
| 107 | 182 |
*/ |
| 108 | 183 |
void |
| 109 | 184 |
init_param1(void) |
| 110 | 185 |
{
|
| 111 |
hz = HZ; |
|
| 186 |
#ifndef XEN |
|
| 187 |
vm_guest = detect_virtual(); |
|
| 188 |
#else |
|
| 189 |
vm_guest = VM_GUEST_XEN; |
|
| 190 |
#endif |
|
| 191 |
hz = -1; |
|
| 112 | 192 |
TUNABLE_INT_FETCH("kern.hz", &hz);
|
| 193 |
if (hz == -1) |
|
| 194 |
hz = vm_guest > VM_GUEST_NO ? HZ_VM : HZ; |
|
| 113 | 195 |
stathz = hz * 128 / 100; |
| 114 | 196 |
profhz = stathz; |
| 115 | 197 |
ustick = 1000000 / hz; |
| ... | ... | |
| 227 | 309 |
TUNABLE_INT_FETCH("kern.ncallout", &ncallout);
|
| 228 | 310 |
} |
| 229 | 311 | |
| 312 |
/* |
|
| 313 |
* Sysctl stringiying handler for kern.vm_guest. |
|
| 314 |
*/ |
|
| 315 |
static int |
|
| 316 |
sysctl_kern_vm_guest(SYSCTL_HANDLER_ARGS) |
|
| 317 |
{
|
|
| 318 |
return (SYSCTL_OUT(req, vm_guest_sysctl_names[vm_guest], |
|
| 319 |
strlen(vm_guest_sysctl_names[vm_guest]))); |
|
| 320 |
} |
|
| b/sys/platform/pc32/i386/initcpu.c | ||
|---|---|---|
| 41 | 41 |
#include <machine/md_var.h> |
| 42 | 42 |
#include <machine/specialreg.h> |
| 43 | 43 | |
| 44 |
#include <vm/vm.h> |
|
| 45 |
#include <vm/pmap.h> |
|
| 46 | ||
| 47 |
#if !defined(CPU_DISABLE_SSE) && defined(I686_CPU) |
|
| 48 |
#define CPU_ENABLE_SSE |
|
| 49 |
#endif |
|
| 50 | ||
| 44 | 51 |
void initializecpu(void); |
| 45 | 52 |
#if defined(I586_CPU) && defined(CPU_WT_ALLOC) |
| 46 | 53 |
void enable_K5_wt_alloc(void); |
| ... | ... | |
| 68 | 75 |
static int hw_instruction_sse; |
| 69 | 76 |
SYSCTL_INT(_hw, OID_AUTO, instruction_sse, CTLFLAG_RD, |
| 70 | 77 |
&hw_instruction_sse, 0, "SIMD/MMX2 instructions available in CPU"); |
| 78 |
/* |
|
| 79 |
* -1: automatic (default) |
|
| 80 |
* 0: keep enable CLFLUSH |
|
| 81 |
* 1: force disable CLFLUSH |
|
| 82 |
*/ |
|
| 83 |
static int hw_clflush_disable = -1; |
|
| 71 | 84 | |
| 72 | 85 |
/* Must *NOT* be BSS or locore will bzero these after setting them */ |
| 73 | 86 |
int cpu = 0; /* Are we 386, 386sx, 486, etc? */ |
| ... | ... | |
| 84 | 97 |
u_int cpu_procinfo2 = 0; /* Multicore info */ |
| 85 | 98 |
char cpu_vendor[20] = ""; /* CPU Origin code */ |
| 86 | 99 |
u_int cpu_vendor_id = 0; /* CPU vendor ID */ |
| 100 |
u_int cpu_clflush_line_size = 32; |
|
| 87 | 101 | |
| 88 | 102 |
SYSCTL_UINT(_hw, OID_AUTO, via_feature_rng, CTLFLAG_RD, |
| 89 | 103 |
&via_feature_rng, 0, "VIA C3/C7 RNG feature available in CPU"); |
| 90 | 104 |
SYSCTL_UINT(_hw, OID_AUTO, via_feature_xcrypt, CTLFLAG_RD, |
| 91 | 105 |
&via_feature_xcrypt, 0, "VIA C3/C7 xcrypt feature available in CPU"); |
| 92 | 106 | |
| 107 |
#if 0 |
|
| 93 | 108 |
#ifndef CPU_DISABLE_SSE |
| 94 | 109 |
u_int cpu_fxsr; /* SSE enabled */ |
| 95 | 110 |
#endif |
| 111 |
#endif |
|
| 112 |
#ifdef CPU_ENABLE_SSE |
|
| 113 |
u_int cpu_fxsr; /* SSE enabled */ |
|
| 114 |
#if 0 |
|
| 115 |
u_int cpu_mxcsr_mask; /* valid bits in mxcsr */ |
|
| 116 |
#endif |
|
| 117 |
#endif |
|
| 96 | 118 | |
| 97 | 119 |
#ifdef I486_CPU |
| 98 | 120 |
/* |
| ... | ... | |
| 588 | 610 |
void |
| 589 | 611 |
enable_sse(void) |
| 590 | 612 |
{
|
| 613 |
#if 0 |
|
| 591 | 614 |
#ifndef CPU_DISABLE_SSE |
| 592 | 615 |
if ((cpu_feature & CPUID_SSE) && (cpu_feature & CPUID_FXSR)) {
|
| 593 | 616 |
load_cr4(rcr4() | CR4_FXSR | CR4_XMM); |
| 594 | 617 |
cpu_fxsr = hw_instruction_sse = 1; |
| 595 | 618 |
} |
| 596 | 619 |
#endif |
| 620 |
#endif |
|
| 621 |
#if defined(CPU_ENABLE_SSE) |
|
| 622 |
if ((cpu_feature & CPUID_XMM) && (cpu_feature & CPUID_FXSR)) {
|
|
| 623 |
load_cr4(rcr4() | CR4_FXSR | CR4_XMM); |
|
| 624 |
cpu_fxsr = hw_instruction_sse = 1; |
|
| 625 |
} |
|
| 626 |
#endif |
|
| 597 | 627 |
} |
| 598 | 628 | |
| 599 | 629 |
#ifdef I686_CPU |
| ... | ... | |
| 685 | 715 |
break; |
| 686 | 716 |
} |
| 687 | 717 |
enable_sse(); |
| 718 | ||
| 719 |
/* |
|
| 720 |
* CPUID with %eax = 1, %ebx returns |
|
| 721 |
* Bits 15-8: CLFLUSH line size |
|
| 722 |
* (Value * 8 = cache line size in bytes) |
|
| 723 |
*/ |
|
| 724 |
if ((cpu_feature & CPUID_CLFSH) != 0) |
|
| 725 |
cpu_clflush_line_size = ((cpu_procinfo >> 8) & 0xff) * 8; |
|
| 726 |
/* |
|
| 727 |
* XXXKIB: (temporary) hack to work around traps generated |
|
| 728 |
* when CLFLUSHing APIC register window under virtualization |
|
| 729 |
* environments. These environments tend to disable the |
|
| 730 |
* CPUID_SS feature even though the native CPU supports it. |
|
| 731 |
*/ |
|
| 732 |
TUNABLE_INT_FETCH("hw.clflush_disable", &hw_clflush_disable);
|
|
| 733 |
if (vm_guest != VM_GUEST_NO && hw_clflush_disable == -1) |
|
| 734 |
cpu_feature &= ~CPUID_CLFSH; |
|
| 735 |
/* |
|
| 736 |
* Allow to disable CLFLUSH feature manually by |
|
| 737 |
* hw.clflush_disable tunable. |
|
| 738 |
*/ |
|
| 739 |
if (hw_clflush_disable == 1) |
|
| 740 |
cpu_feature &= ~CPUID_CLFSH; |
|
| 688 | 741 |
} |
| 689 | 742 | |
| 690 | 743 |
#if defined(I586_CPU) && defined(CPU_WT_ALLOC) |
| b/sys/platform/pc32/include/md_var.h | ||
|---|---|---|
| 61 | 61 |
extern u_int amd_feature2; |
| 62 | 62 |
extern u_int via_feature_rng; |
| 63 | 63 |
extern u_int via_feature_xcrypt; |
| 64 |
extern u_int cpu_clflush_line_size; |
|
| 64 | 65 |
extern u_int cpu_fxsr; |
| 65 | 66 |
extern u_int cpu_high; |
| 66 | 67 |
extern u_int cpu_id; |
| b/sys/platform/pc64/include/md_var.h | ||
|---|---|---|
| 49 | 49 |
extern u_int via_feature_xcrypt; |
| 50 | 50 |
extern u_int amd_feature; |
| 51 | 51 |
extern u_int amd_feature2; |
| 52 |
extern u_int cpu_clflush_line_size; |
|
| 52 | 53 |
extern u_int cpu_fxsr; |
| 53 | 54 |
extern u_int cpu_high; |
| 54 | 55 |
extern u_int cpu_id; |
| ... | ... | |
| 101 | 102 |
void minidumpsys(struct dumperinfo *); |
| 102 | 103 |
void dump_add_page(vm_paddr_t); |
| 103 | 104 |
void dump_drop_page(vm_paddr_t); |
| 105 |
#if 0 |
|
| 106 |
void initializecpu(void); |
|
| 107 |
#endif |
|
| 108 |
void initializecpucache(void); |
|
| 104 | 109 | |
| 105 | 110 |
#endif /* !_MACHINE_MD_VAR_H_ */ |
| b/sys/platform/pc64/x86_64/initcpu.c | ||
|---|---|---|
| 46 | 46 |
static int hw_instruction_sse; |
| 47 | 47 |
SYSCTL_INT(_hw, OID_AUTO, instruction_sse, CTLFLAG_RD, |
| 48 | 48 |
&hw_instruction_sse, 0, "SIMD/MMX2 instructions available in CPU"); |
| 49 |
/* |
|
| 50 |
* -1: automatic (default) |
|
| 51 |
* 0: keep enable CLFLUSH |
|
| 52 |
* 1: force disable CLFLUSH |
|
| 53 |
*/ |
|
| 54 |
static int hw_clflush_disable = -1; |
|
| 49 | 55 | |
| 50 | 56 |
int cpu; /* Are we 386, 386sx, 486, etc? */ |
| 51 | 57 |
u_int cpu_feature; /* Feature flags */ |
| ... | ... | |
| 63 | 69 |
u_int cpu_vendor_id; /* CPU vendor ID */ |
| 64 | 70 |
u_int cpu_fxsr; /* SSE enabled */ |
| 65 | 71 |
u_int cpu_mxcsr_mask; /* Valid bits in mxcsr */ |
| 72 |
u_int cpu_clflush_line_size = 32; |
|
| 66 | 73 | |
| 67 | 74 |
SYSCTL_UINT(_hw, OID_AUTO, via_feature_rng, CTLFLAG_RD, |
| 68 | 75 |
&via_feature_rng, 0, "VIA C3/C7 RNG feature available in CPU"); |
| ... | ... | |
| 180 | 187 |
CPUID_TO_MODEL(cpu_id) >= 0xf) |
| 181 | 188 |
init_via(); |
| 182 | 189 |
} |
| 190 | ||
| 191 |
void |
|
| 192 |
initializecpucache(void) |
|
| 193 |
{
|
|
| 194 | ||
| 195 |
/* |
|
| 196 |
* CPUID with %eax = 1, %ebx returns |
|
| 197 |
* Bits 15-8: CLFLUSH line size |
|
| 198 |
* (Value * 8 = cache line size in bytes) |
|
| 199 |
*/ |
|
| 200 |
if ((cpu_feature & CPUID_CLFSH) != 0) |
|
| 201 |
cpu_clflush_line_size = ((cpu_procinfo >> 8) & 0xff) * 8; |
|
| 202 |
/* |
|
| 203 |
* XXXKIB: (temporary) hack to work around traps generated |
|
| 204 |
* when CLFLUSHing APIC register window under virtualization |
|
| 205 |
* environments. These environments tend to disable the |
|
| 206 |
* CPUID_SS feature even though the native CPU supports it. |
|
| 207 |
*/ |
|
| 208 |
TUNABLE_INT_FETCH("hw.clflush_disable", &hw_clflush_disable);
|
|
| 209 |
if (vm_guest != VM_GUEST_NO && hw_clflush_disable == -1) |
|
| 210 |
cpu_feature &= ~CPUID_CLFSH; |
|
| 211 |
/* |
|
| 212 |
* Allow to disable CLFLUSH feature manually by |
|
| 213 |
* hw.clflush_disable tunable. |
|
| 214 |
*/ |
|
| 215 |
if (hw_clflush_disable == 1) |
|
| 216 |
cpu_feature &= ~CPUID_CLFSH; |
|
| 217 |
} |
|
| b/sys/platform/pc64/x86_64/machdep.c | ||
|---|---|---|
| 1905 | 1905 |
#endif |
| 1906 | 1906 |
identify_cpu(); /* Final stage of CPU initialization */ |
| 1907 | 1907 |
initializecpu(); /* Initialize CPU registers */ |
| 1908 |
initializecpucache(); |
|
| 1908 | 1909 | |
| 1909 | 1910 |
TUNABLE_INT_FETCH("hw.apic_io_enable", &ioapic_enable); /* for compat */
|
| 1910 | 1911 |
TUNABLE_INT_FETCH("hw.ioapic_enable", &ioapic_enable);
|
| b/sys/sys/systm.h | ||
|---|---|---|
| 85 | 85 | |
| 86 | 86 |
extern int maxusers; /* system tune hint */ |
| 87 | 87 | |
| 88 |
extern int vm_guest; /* Running as virtual machine guest? */ |
|
| 89 | ||
| 90 |
/* |
|
| 91 |
* Detected virtual machine guest types. The intention is to expand |
|
| 92 |
* and/or add to the VM_GUEST_VM type if specific VM functionality is |
|
| 93 |
* ever implemented (e.g. vendor-specific paravirtualization features). |
|
| 94 |
*/ |
|
| 95 |
enum VM_GUEST { VM_GUEST_NO = 0, VM_GUEST_VM, VM_GUEST_XEN };
|
|
| 96 | ||
| 88 | 97 |
extern int ncpus; /* total number of cpus (real, hyper, virtual)*/ |
| 89 | 98 |
extern int ncpus2; /* ncpus rounded down to power of 2 */ |
| 90 | 99 |
extern int ncpus2_shift; /* log base 2 of ncpus2 */ |