Revision 7ba1e619 target-i386/helper.c
b/target-i386/helper.c | ||
---|---|---|
29 | 29 |
#include "exec-all.h" |
30 | 30 |
#include "svm.h" |
31 | 31 |
#include "qemu-common.h" |
32 |
#include "kvm.h" |
|
32 | 33 |
|
33 | 34 |
//#define DEBUG_MMU |
34 | 35 |
|
... | ... | |
115 | 116 |
#ifdef USE_KQEMU |
116 | 117 |
kqemu_init(env); |
117 | 118 |
#endif |
119 |
if (kvm_enabled()) |
|
120 |
kvm_init_vcpu(env); |
|
118 | 121 |
return env; |
119 | 122 |
} |
120 | 123 |
|
... | ... | |
1288 | 1291 |
} |
1289 | 1292 |
#endif /* !CONFIG_USER_ONLY */ |
1290 | 1293 |
|
1294 |
#if defined(CONFIG_KVM) |
|
1295 |
static void host_cpuid(uint32_t function, uint32_t *eax, uint32_t *ebx, |
|
1296 |
uint32_t *ecx, uint32_t *edx) |
|
1297 |
{ |
|
1298 |
uint32_t vec[4]; |
|
1299 |
|
|
1300 |
#ifdef __x86_64__ |
|
1301 |
asm volatile("cpuid" |
|
1302 |
: "=a"(vec[0]), "=b"(vec[1]), |
|
1303 |
"=c"(vec[2]), "=d"(vec[3]) |
|
1304 |
: "0"(function) : "cc"); |
|
1305 |
#else |
|
1306 |
asm volatile("pusha \n\t" |
|
1307 |
"cpuid \n\t" |
|
1308 |
"mov %%eax, 0(%1) \n\t" |
|
1309 |
"mov %%ebx, 4(%1) \n\t" |
|
1310 |
"mov %%ecx, 8(%1) \n\t" |
|
1311 |
"mov %%edx, 12(%1) \n\t" |
|
1312 |
"popa" |
|
1313 |
: : "a"(function), "S"(vec) |
|
1314 |
: "memory", "cc"); |
|
1315 |
#endif |
|
1316 |
|
|
1317 |
if (eax) |
|
1318 |
*eax = vec[0]; |
|
1319 |
if (ebx) |
|
1320 |
*ebx = vec[1]; |
|
1321 |
if (ecx) |
|
1322 |
*ecx = vec[2]; |
|
1323 |
if (edx) |
|
1324 |
*edx = vec[3]; |
|
1325 |
} |
|
1326 |
#endif |
|
1327 |
|
|
1291 | 1328 |
void cpu_x86_cpuid(CPUX86State *env, uint32_t index, |
1292 | 1329 |
uint32_t *eax, uint32_t *ebx, |
1293 | 1330 |
uint32_t *ecx, uint32_t *edx) |
... | ... | |
1307 | 1344 |
*ebx = env->cpuid_vendor1; |
1308 | 1345 |
*edx = env->cpuid_vendor2; |
1309 | 1346 |
*ecx = env->cpuid_vendor3; |
1347 |
|
|
1348 |
/* sysenter isn't supported on compatibility mode on AMD. and syscall |
|
1349 |
* isn't supported in compatibility mode on Intel. so advertise the |
|
1350 |
* actuall cpu, and say goodbye to migration between different vendors |
|
1351 |
* is you use compatibility mode. */ |
|
1352 |
if (kvm_enabled()) |
|
1353 |
host_cpuid(0, NULL, ebx, ecx, edx); |
|
1310 | 1354 |
break; |
1311 | 1355 |
case 1: |
1312 | 1356 |
*eax = env->cpuid_version; |
1313 | 1357 |
*ebx = (env->cpuid_apic_id << 24) | 8 << 8; /* CLFLUSH size in quad words, Linux wants it. */ |
1314 | 1358 |
*ecx = env->cpuid_ext_features; |
1315 | 1359 |
*edx = env->cpuid_features; |
1360 |
|
|
1361 |
/* "Hypervisor present" bit required for Microsoft SVVP */ |
|
1362 |
if (kvm_enabled()) |
|
1363 |
*ecx |= (1 << 31); |
|
1316 | 1364 |
break; |
1317 | 1365 |
case 2: |
1318 | 1366 |
/* cache info: needed for Pentium Pro compatibility */ |
... | ... | |
1390 | 1438 |
*ebx = 0; |
1391 | 1439 |
*ecx = env->cpuid_ext3_features; |
1392 | 1440 |
*edx = env->cpuid_ext2_features; |
1441 |
|
|
1442 |
if (kvm_enabled()) { |
|
1443 |
uint32_t h_eax, h_edx; |
|
1444 |
|
|
1445 |
host_cpuid(0x80000001, &h_eax, NULL, NULL, &h_edx); |
|
1446 |
|
|
1447 |
/* disable CPU features that the host does not support */ |
|
1448 |
|
|
1449 |
/* long mode */ |
|
1450 |
if ((h_edx & 0x20000000) == 0 /* || !lm_capable_kernel */) |
|
1451 |
*edx &= ~0x20000000; |
|
1452 |
/* syscall */ |
|
1453 |
if ((h_edx & 0x00000800) == 0) |
|
1454 |
*edx &= ~0x00000800; |
|
1455 |
/* nx */ |
|
1456 |
if ((h_edx & 0x00100000) == 0) |
|
1457 |
*edx &= ~0x00100000; |
|
1458 |
|
|
1459 |
/* disable CPU features that KVM cannot support */ |
|
1460 |
|
|
1461 |
/* svm */ |
|
1462 |
*ecx &= ~4UL; |
|
1463 |
/* 3dnow */ |
|
1464 |
*edx = ~0xc0000000; |
|
1465 |
} |
|
1393 | 1466 |
break; |
1394 | 1467 |
case 0x80000002: |
1395 | 1468 |
case 0x80000003: |
Also available in: Unified diff