Revision b8b6a50b target-i386/helper.c
b/target-i386/helper.c | ||
---|---|---|
17 | 17 |
* License along with this library; if not, write to the Free Software |
18 | 18 |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 | 19 |
*/ |
20 |
#define CPU_NO_GLOBAL_REGS |
|
20 | 21 |
#include "exec.h" |
21 | 22 |
#include "host-utils.h" |
22 | 23 |
|
... | ... | |
93 | 94 |
3.32192809488736234781L, /*l2t*/ |
94 | 95 |
}; |
95 | 96 |
|
96 |
/* thread support */ |
|
97 |
/* broken thread support */
|
|
97 | 98 |
|
98 | 99 |
spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED; |
99 | 100 |
|
100 |
void cpu_lock(void)
|
|
101 |
void helper_lock(void)
|
|
101 | 102 |
{ |
102 | 103 |
spin_lock(&global_cpu_lock); |
103 | 104 |
} |
104 | 105 |
|
105 |
void cpu_unlock(void)
|
|
106 |
void helper_unlock(void)
|
|
106 | 107 |
{ |
107 | 108 |
spin_unlock(&global_cpu_lock); |
108 | 109 |
} |
... | ... | |
508 | 509 |
} |
509 | 510 |
} |
510 | 511 |
|
511 |
void check_iob_T0(void)
|
|
512 |
void helper_check_iob(uint32_t t0)
|
|
512 | 513 |
{ |
513 |
check_io(T0, 1);
|
|
514 |
check_io(t0, 1);
|
|
514 | 515 |
} |
515 | 516 |
|
516 |
void check_iow_T0(void)
|
|
517 |
void helper_check_iow(uint32_t t0)
|
|
517 | 518 |
{ |
518 |
check_io(T0, 2);
|
|
519 |
check_io(t0, 2);
|
|
519 | 520 |
} |
520 | 521 |
|
521 |
void check_iol_T0(void)
|
|
522 |
void helper_check_iol(uint32_t t0)
|
|
522 | 523 |
{ |
523 |
check_io(T0, 4);
|
|
524 |
check_io(t0, 4);
|
|
524 | 525 |
} |
525 | 526 |
|
526 |
void check_iob_DX(void)
|
|
527 |
void helper_outb(uint32_t port, uint32_t data)
|
|
527 | 528 |
{ |
528 |
check_io(EDX & 0xffff, 1);
|
|
529 |
cpu_outb(env, port, data & 0xff);
|
|
529 | 530 |
} |
530 | 531 |
|
531 |
void check_iow_DX(void)
|
|
532 |
target_ulong helper_inb(uint32_t port)
|
|
532 | 533 |
{ |
533 |
check_io(EDX & 0xffff, 2);
|
|
534 |
return cpu_inb(env, port);
|
|
534 | 535 |
} |
535 | 536 |
|
536 |
void check_iol_DX(void)
|
|
537 |
void helper_outw(uint32_t port, uint32_t data)
|
|
537 | 538 |
{ |
538 |
check_io(EDX & 0xffff, 4); |
|
539 |
cpu_outw(env, port, data & 0xffff); |
|
540 |
} |
|
541 |
|
|
542 |
target_ulong helper_inw(uint32_t port) |
|
543 |
{ |
|
544 |
return cpu_inw(env, port); |
|
545 |
} |
|
546 |
|
|
547 |
void helper_outl(uint32_t port, uint32_t data) |
|
548 |
{ |
|
549 |
cpu_outl(env, port, data); |
|
550 |
} |
|
551 |
|
|
552 |
target_ulong helper_inl(uint32_t port) |
|
553 |
{ |
|
554 |
return cpu_inl(env, port); |
|
539 | 555 |
} |
540 | 556 |
|
541 | 557 |
static inline unsigned int get_sp_mask(unsigned int e2) |
... | ... | |
1275 | 1291 |
int next_eip_addend) |
1276 | 1292 |
{ |
1277 | 1293 |
if (!is_int) { |
1278 |
svm_check_intercept_param(SVM_EXIT_EXCP_BASE + intno, error_code); |
|
1294 |
helper_svm_check_intercept_param(SVM_EXIT_EXCP_BASE + intno, error_code);
|
|
1279 | 1295 |
intno = check_exception(intno, &error_code); |
1280 | 1296 |
} |
1281 | 1297 |
|
... | ... | |
1857 | 1873 |
FORCE_RET(); |
1858 | 1874 |
} |
1859 | 1875 |
|
1860 |
void helper_cmpxchg8b(void)
|
|
1876 |
void helper_cmpxchg8b(target_ulong a0)
|
|
1861 | 1877 |
{ |
1862 | 1878 |
uint64_t d; |
1863 | 1879 |
int eflags; |
1864 | 1880 |
|
1865 | 1881 |
eflags = cc_table[CC_OP].compute_all(); |
1866 |
d = ldq(A0);
|
|
1882 |
d = ldq(a0);
|
|
1867 | 1883 |
if (d == (((uint64_t)EDX << 32) | EAX)) { |
1868 |
stq(A0, ((uint64_t)ECX << 32) | EBX);
|
|
1884 |
stq(a0, ((uint64_t)ECX << 32) | EBX);
|
|
1869 | 1885 |
eflags |= CC_Z; |
1870 | 1886 |
} else { |
1871 |
EDX = d >> 32;
|
|
1872 |
EAX = d; |
|
1887 |
EDX = (uint32_t)(d >> 32);
|
|
1888 |
EAX = (uint32_t)d;
|
|
1873 | 1889 |
eflags &= ~CC_Z; |
1874 | 1890 |
} |
1875 | 1891 |
CC_SRC = eflags; |
... | ... | |
1986 | 2002 |
} |
1987 | 2003 |
} |
1988 | 2004 |
|
1989 |
void helper_enter_level(int level, int data32) |
|
2005 |
void helper_enter_level(int level, int data32, target_ulong t1)
|
|
1990 | 2006 |
{ |
1991 | 2007 |
target_ulong ssp; |
1992 | 2008 |
uint32_t esp_mask, esp, ebp; |
... | ... | |
2004 | 2020 |
stl(ssp + (esp & esp_mask), ldl(ssp + (ebp & esp_mask))); |
2005 | 2021 |
} |
2006 | 2022 |
esp -= 4; |
2007 |
stl(ssp + (esp & esp_mask), T1);
|
|
2023 |
stl(ssp + (esp & esp_mask), t1);
|
|
2008 | 2024 |
} else { |
2009 | 2025 |
/* 16 bit */ |
2010 | 2026 |
esp -= 2; |
... | ... | |
2014 | 2030 |
stw(ssp + (esp & esp_mask), lduw(ssp + (ebp & esp_mask))); |
2015 | 2031 |
} |
2016 | 2032 |
esp -= 2; |
2017 |
stw(ssp + (esp & esp_mask), T1);
|
|
2033 |
stw(ssp + (esp & esp_mask), t1);
|
|
2018 | 2034 |
} |
2019 | 2035 |
} |
2020 | 2036 |
|
2021 | 2037 |
#ifdef TARGET_X86_64 |
2022 |
void helper_enter64_level(int level, int data64) |
|
2038 |
void helper_enter64_level(int level, int data64, target_ulong t1)
|
|
2023 | 2039 |
{ |
2024 | 2040 |
target_ulong esp, ebp; |
2025 | 2041 |
ebp = EBP; |
... | ... | |
2034 | 2050 |
stq(esp, ldq(ebp)); |
2035 | 2051 |
} |
2036 | 2052 |
esp -= 8; |
2037 |
stq(esp, T1);
|
|
2053 |
stq(esp, t1);
|
|
2038 | 2054 |
} else { |
2039 | 2055 |
/* 16 bit */ |
2040 | 2056 |
esp -= 2; |
... | ... | |
2044 | 2060 |
stw(esp, lduw(ebp)); |
2045 | 2061 |
} |
2046 | 2062 |
esp -= 2; |
2047 |
stw(esp, T1);
|
|
2063 |
stw(esp, t1);
|
|
2048 | 2064 |
} |
2049 | 2065 |
} |
2050 | 2066 |
#endif |
... | ... | |
2231 | 2247 |
} |
2232 | 2248 |
|
2233 | 2249 |
/* protected mode jump */ |
2234 |
void helper_ljmp_protected_T0_T1(int next_eip_addend) |
|
2250 |
void helper_ljmp_protected(int new_cs, target_ulong new_eip, |
|
2251 |
int next_eip_addend) |
|
2235 | 2252 |
{ |
2236 |
int new_cs, gate_cs, type;
|
|
2253 |
int gate_cs, type; |
|
2237 | 2254 |
uint32_t e1, e2, cpl, dpl, rpl, limit; |
2238 |
target_ulong new_eip, next_eip;
|
|
2255 |
target_ulong next_eip; |
|
2239 | 2256 |
|
2240 |
new_cs = T0; |
|
2241 |
new_eip = T1; |
|
2242 | 2257 |
if ((new_cs & 0xfffc) == 0) |
2243 | 2258 |
raise_exception_err(EXCP0D_GPF, 0); |
2244 | 2259 |
if (load_segment(&e1, &e2, new_cs) != 0) |
... | ... | |
2322 | 2337 |
} |
2323 | 2338 |
|
2324 | 2339 |
/* real mode call */ |
2325 |
void helper_lcall_real_T0_T1(int shift, int next_eip) |
|
2340 |
void helper_lcall_real(int new_cs, target_ulong new_eip1, |
|
2341 |
int shift, int next_eip) |
|
2326 | 2342 |
{ |
2327 |
int new_cs, new_eip;
|
|
2343 |
int new_eip; |
|
2328 | 2344 |
uint32_t esp, esp_mask; |
2329 | 2345 |
target_ulong ssp; |
2330 | 2346 |
|
2331 |
new_cs = T0; |
|
2332 |
new_eip = T1; |
|
2347 |
new_eip = new_eip1; |
|
2333 | 2348 |
esp = ESP; |
2334 | 2349 |
esp_mask = get_sp_mask(env->segs[R_SS].flags); |
2335 | 2350 |
ssp = env->segs[R_SS].base; |
... | ... | |
2348 | 2363 |
} |
2349 | 2364 |
|
2350 | 2365 |
/* protected mode call */ |
2351 |
void helper_lcall_protected_T0_T1(int shift, int next_eip_addend) |
|
2366 |
void helper_lcall_protected(int new_cs, target_ulong new_eip, |
|
2367 |
int shift, int next_eip_addend) |
|
2352 | 2368 |
{ |
2353 |
int new_cs, new_stack, i;
|
|
2369 |
int new_stack, i; |
|
2354 | 2370 |
uint32_t e1, e2, cpl, dpl, rpl, selector, offset, param_count; |
2355 | 2371 |
uint32_t ss, ss_e1, ss_e2, sp, type, ss_dpl, sp_mask; |
2356 | 2372 |
uint32_t val, limit, old_sp_mask; |
2357 |
target_ulong ssp, old_ssp, next_eip, new_eip;
|
|
2373 |
target_ulong ssp, old_ssp, next_eip; |
|
2358 | 2374 |
|
2359 |
new_cs = T0; |
|
2360 |
new_eip = T1; |
|
2361 | 2375 |
next_eip = env->eip + next_eip_addend; |
2362 | 2376 |
#ifdef DEBUG_PCALL |
2363 | 2377 |
if (loglevel & CPU_LOG_PCALL) { |
... | ... | |
2922 | 2936 |
#endif |
2923 | 2937 |
} |
2924 | 2938 |
|
2925 |
void helper_movl_crN_T0(int reg) |
|
2939 |
void helper_movl_crN_T0(int reg, target_ulong t0)
|
|
2926 | 2940 |
{ |
2927 | 2941 |
#if !defined(CONFIG_USER_ONLY) |
2928 | 2942 |
switch(reg) { |
2929 | 2943 |
case 0: |
2930 |
cpu_x86_update_cr0(env, T0);
|
|
2944 |
cpu_x86_update_cr0(env, t0);
|
|
2931 | 2945 |
break; |
2932 | 2946 |
case 3: |
2933 |
cpu_x86_update_cr3(env, T0);
|
|
2947 |
cpu_x86_update_cr3(env, t0);
|
|
2934 | 2948 |
break; |
2935 | 2949 |
case 4: |
2936 |
cpu_x86_update_cr4(env, T0);
|
|
2950 |
cpu_x86_update_cr4(env, t0);
|
|
2937 | 2951 |
break; |
2938 | 2952 |
case 8: |
2939 |
cpu_set_apic_tpr(env, T0);
|
|
2940 |
env->cr[8] = T0;
|
|
2953 |
cpu_set_apic_tpr(env, t0);
|
|
2954 |
env->cr[8] = t0;
|
|
2941 | 2955 |
break; |
2942 | 2956 |
default: |
2943 |
env->cr[reg] = T0;
|
|
2957 |
env->cr[reg] = t0;
|
|
2944 | 2958 |
break; |
2945 | 2959 |
} |
2946 | 2960 |
#endif |
2947 | 2961 |
} |
2948 | 2962 |
|
2963 |
void helper_lmsw(target_ulong t0) |
|
2964 |
{ |
|
2965 |
/* only 4 lower bits of CR0 are modified. PE cannot be set to zero |
|
2966 |
if already set to one. */ |
|
2967 |
t0 = (env->cr[0] & ~0xe) | (t0 & 0xf); |
|
2968 |
helper_movl_crN_T0(0, t0); |
|
2969 |
} |
|
2970 |
|
|
2971 |
void helper_clts(void) |
|
2972 |
{ |
|
2973 |
env->cr[0] &= ~CR0_TS_MASK; |
|
2974 |
env->hflags &= ~HF_TS_MASK; |
|
2975 |
} |
|
2976 |
|
|
2977 |
#if !defined(CONFIG_USER_ONLY) |
|
2978 |
target_ulong helper_movtl_T0_cr8(void) |
|
2979 |
{ |
|
2980 |
return cpu_get_apic_tpr(env); |
|
2981 |
} |
|
2982 |
#endif |
|
2983 |
|
|
2949 | 2984 |
/* XXX: do more */ |
2950 |
void helper_movl_drN_T0(int reg) |
|
2985 |
void helper_movl_drN_T0(int reg, target_ulong t0)
|
|
2951 | 2986 |
{ |
2952 |
env->dr[reg] = T0;
|
|
2987 |
env->dr[reg] = t0;
|
|
2953 | 2988 |
} |
2954 | 2989 |
|
2955 | 2990 |
void helper_invlpg(target_ulong addr) |
... | ... | |
2975 | 3010 |
raise_exception(EXCP0D_GPF); |
2976 | 3011 |
} |
2977 | 3012 |
|
2978 |
if (!svm_check_intercept_param(SVM_EXIT_RDPMC, 0)) {
|
|
2979 |
/* currently unimplemented */ |
|
2980 |
raise_exception_err(EXCP06_ILLOP, 0);
|
|
2981 |
}
|
|
3013 |
helper_svm_check_intercept_param(SVM_EXIT_RDPMC, 0);
|
|
3014 |
|
|
3015 |
/* currently unimplemented */
|
|
3016 |
raise_exception_err(EXCP06_ILLOP, 0);
|
|
2982 | 3017 |
} |
2983 | 3018 |
|
2984 | 3019 |
#if defined(CONFIG_USER_ONLY) |
... | ... | |
3118 | 3153 |
} |
3119 | 3154 |
#endif |
3120 | 3155 |
|
3121 |
void helper_lsl(uint32_t selector)
|
|
3156 |
uint32_t helper_lsl(uint32_t selector)
|
|
3122 | 3157 |
{ |
3123 | 3158 |
unsigned int limit; |
3124 | 3159 |
uint32_t e1, e2, eflags; |
... | ... | |
3153 | 3188 |
if (dpl < cpl || dpl < rpl) { |
3154 | 3189 |
fail: |
3155 | 3190 |
CC_SRC = eflags & ~CC_Z; |
3156 |
return; |
|
3191 |
return 0;
|
|
3157 | 3192 |
} |
3158 | 3193 |
} |
3159 | 3194 |
limit = get_seg_limit(e1, e2); |
3160 |
T1 = limit; |
|
3161 | 3195 |
CC_SRC = eflags | CC_Z; |
3196 |
return limit; |
|
3162 | 3197 |
} |
3163 | 3198 |
|
3164 |
void helper_lar(uint32_t selector)
|
|
3199 |
uint32_t helper_lar(uint32_t selector)
|
|
3165 | 3200 |
{ |
3166 | 3201 |
uint32_t e1, e2, eflags; |
3167 | 3202 |
int rpl, dpl, cpl, type; |
... | ... | |
3200 | 3235 |
if (dpl < cpl || dpl < rpl) { |
3201 | 3236 |
fail: |
3202 | 3237 |
CC_SRC = eflags & ~CC_Z; |
3203 |
return; |
|
3238 |
return 0;
|
|
3204 | 3239 |
} |
3205 | 3240 |
} |
3206 |
T1 = e2 & 0x00f0ff00; |
|
3207 | 3241 |
CC_SRC = eflags | CC_Z; |
3242 |
return e2 & 0x00f0ff00; |
|
3208 | 3243 |
} |
3209 | 3244 |
|
3210 | 3245 |
void helper_verr(uint32_t selector) |
... | ... | |
4412 | 4447 |
return 0; |
4413 | 4448 |
} |
4414 | 4449 |
|
4415 |
void helper_mulq_EAX_T0(void)
|
|
4450 |
void helper_mulq_EAX_T0(target_ulong t0)
|
|
4416 | 4451 |
{ |
4417 | 4452 |
uint64_t r0, r1; |
4418 | 4453 |
|
4419 |
mulu64(&r0, &r1, EAX, T0);
|
|
4454 |
mulu64(&r0, &r1, EAX, t0);
|
|
4420 | 4455 |
EAX = r0; |
4421 | 4456 |
EDX = r1; |
4422 | 4457 |
CC_DST = r0; |
4423 | 4458 |
CC_SRC = r1; |
4424 | 4459 |
} |
4425 | 4460 |
|
4426 |
void helper_imulq_EAX_T0(void)
|
|
4461 |
void helper_imulq_EAX_T0(target_ulong t0)
|
|
4427 | 4462 |
{ |
4428 | 4463 |
uint64_t r0, r1; |
4429 | 4464 |
|
4430 |
muls64(&r0, &r1, EAX, T0);
|
|
4465 |
muls64(&r0, &r1, EAX, t0);
|
|
4431 | 4466 |
EAX = r0; |
4432 | 4467 |
EDX = r1; |
4433 | 4468 |
CC_DST = r0; |
4434 | 4469 |
CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63)); |
4435 | 4470 |
} |
4436 | 4471 |
|
4437 |
void helper_imulq_T0_T1(void)
|
|
4472 |
target_ulong helper_imulq_T0_T1(target_ulong t0, target_ulong t1)
|
|
4438 | 4473 |
{ |
4439 | 4474 |
uint64_t r0, r1; |
4440 | 4475 |
|
4441 |
muls64(&r0, &r1, T0, T1); |
|
4442 |
T0 = r0; |
|
4476 |
muls64(&r0, &r1, t0, t1); |
|
4443 | 4477 |
CC_DST = r0; |
4444 | 4478 |
CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63)); |
4479 |
return r0; |
|
4445 | 4480 |
} |
4446 | 4481 |
|
4447 | 4482 |
void helper_divq_EAX(target_ulong t0) |
... | ... | |
4553 | 4588 |
env->hflags &= ~HF_INHIBIT_IRQ_MASK; |
4554 | 4589 |
} |
4555 | 4590 |
|
4556 |
void helper_boundw(void)
|
|
4591 |
void helper_boundw(target_ulong a0, int v)
|
|
4557 | 4592 |
{ |
4558 |
int low, high, v;
|
|
4559 |
low = ldsw(A0);
|
|
4560 |
high = ldsw(A0 + 2);
|
|
4561 |
v = (int16_t)T0;
|
|
4593 |
int low, high; |
|
4594 |
low = ldsw(a0);
|
|
4595 |
high = ldsw(a0 + 2);
|
|
4596 |
v = (int16_t)v;
|
|
4562 | 4597 |
if (v < low || v > high) { |
4563 | 4598 |
raise_exception(EXCP05_BOUND); |
4564 | 4599 |
} |
4565 | 4600 |
FORCE_RET(); |
4566 | 4601 |
} |
4567 | 4602 |
|
4568 |
void helper_boundl(void)
|
|
4603 |
void helper_boundl(target_ulong a0, int v)
|
|
4569 | 4604 |
{ |
4570 |
int low, high, v; |
|
4571 |
low = ldl(A0); |
|
4572 |
high = ldl(A0 + 4); |
|
4573 |
v = T0; |
|
4605 |
int low, high; |
|
4606 |
low = ldl(a0); |
|
4607 |
high = ldl(a0 + 4); |
|
4574 | 4608 |
if (v < low || v > high) { |
4575 | 4609 |
raise_exception(EXCP05_BOUND); |
4576 | 4610 |
} |
... | ... | |
4661 | 4695 |
|
4662 | 4696 |
#if defined(CONFIG_USER_ONLY) |
4663 | 4697 |
|
4664 |
void helper_vmrun(void) { } |
|
4665 |
void helper_vmmcall(void) { } |
|
4666 |
void helper_vmload(void) { } |
|
4667 |
void helper_vmsave(void) { } |
|
4668 |
void helper_skinit(void) { } |
|
4669 |
void helper_invlpga(void) { } |
|
4670 |
void vmexit(uint64_t exit_code, uint64_t exit_info_1) { } |
|
4671 |
int svm_check_intercept_param(uint32_t type, uint64_t param) |
|
4698 |
void helper_vmrun(void) |
|
4699 |
{ |
|
4700 |
} |
|
4701 |
void helper_vmmcall(void) |
|
4702 |
{ |
|
4703 |
} |
|
4704 |
void helper_vmload(void) |
|
4705 |
{ |
|
4706 |
} |
|
4707 |
void helper_vmsave(void) |
|
4708 |
{ |
|
4709 |
} |
|
4710 |
void helper_skinit(void) |
|
4711 |
{ |
|
4712 |
} |
|
4713 |
void helper_invlpga(void) |
|
4714 |
{ |
|
4715 |
} |
|
4716 |
void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1) |
|
4717 |
{ |
|
4718 |
} |
|
4719 |
void helper_svm_check_intercept_param(uint32_t type, uint64_t param) |
|
4672 | 4720 |
{ |
4673 |
return 0; |
|
4674 | 4721 |
} |
4675 | 4722 |
|
4723 |
void helper_svm_check_io(uint32_t port, uint32_t param, |
|
4724 |
uint32_t next_eip_addend) |
|
4725 |
{ |
|
4726 |
} |
|
4676 | 4727 |
#else |
4677 | 4728 |
|
4678 | 4729 |
static inline uint32_t |
... | ... | |
4702 | 4753 |
fprintf(logfile,"vmrun! " TARGET_FMT_lx "\n", addr); |
4703 | 4754 |
|
4704 | 4755 |
env->vm_vmcb = addr; |
4705 |
regs_to_env(); |
|
4706 | 4756 |
|
4707 | 4757 |
/* save the current CPU state in the hsave page */ |
4708 | 4758 |
stq_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.base), env->gdt.base); |
... | ... | |
4801 | 4851 |
|
4802 | 4852 |
helper_stgi(); |
4803 | 4853 |
|
4804 |
regs_to_env(); |
|
4805 |
|
|
4806 | 4854 |
/* maybe we need to inject an event */ |
4807 | 4855 |
event_inj = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj)); |
4808 | 4856 |
if (event_inj & SVM_EVTINJ_VALID) { |
... | ... | |
4927 | 4975 |
tlb_flush(env, 0); |
4928 | 4976 |
} |
4929 | 4977 |
|
4930 |
int svm_check_intercept_param(uint32_t type, uint64_t param)
|
|
4978 |
void helper_svm_check_intercept_param(uint32_t type, uint64_t param)
|
|
4931 | 4979 |
{ |
4932 | 4980 |
switch(type) { |
4933 | 4981 |
case SVM_EXIT_READ_CR0 ... SVM_EXIT_READ_CR0 + 8: |
4934 | 4982 |
if (INTERCEPTEDw(_cr_read, (1 << (type - SVM_EXIT_READ_CR0)))) { |
4935 |
vmexit(type, param); |
|
4936 |
return 1; |
|
4983 |
helper_vmexit(type, param); |
|
4937 | 4984 |
} |
4938 | 4985 |
break; |
4939 | 4986 |
case SVM_EXIT_READ_DR0 ... SVM_EXIT_READ_DR0 + 8: |
4940 | 4987 |
if (INTERCEPTEDw(_dr_read, (1 << (type - SVM_EXIT_READ_DR0)))) { |
4941 |
vmexit(type, param); |
|
4942 |
return 1; |
|
4988 |
helper_vmexit(type, param); |
|
4943 | 4989 |
} |
4944 | 4990 |
break; |
4945 | 4991 |
case SVM_EXIT_WRITE_CR0 ... SVM_EXIT_WRITE_CR0 + 8: |
4946 | 4992 |
if (INTERCEPTEDw(_cr_write, (1 << (type - SVM_EXIT_WRITE_CR0)))) { |
4947 |
vmexit(type, param); |
|
4948 |
return 1; |
|
4993 |
helper_vmexit(type, param); |
|
4949 | 4994 |
} |
4950 | 4995 |
break; |
4951 | 4996 |
case SVM_EXIT_WRITE_DR0 ... SVM_EXIT_WRITE_DR0 + 8: |
4952 | 4997 |
if (INTERCEPTEDw(_dr_write, (1 << (type - SVM_EXIT_WRITE_DR0)))) { |
4953 |
vmexit(type, param); |
|
4954 |
return 1; |
|
4998 |
helper_vmexit(type, param); |
|
4955 | 4999 |
} |
4956 | 5000 |
break; |
4957 | 5001 |
case SVM_EXIT_EXCP_BASE ... SVM_EXIT_EXCP_BASE + 16: |
4958 | 5002 |
if (INTERCEPTEDl(_exceptions, (1 << (type - SVM_EXIT_EXCP_BASE)))) { |
4959 |
vmexit(type, param); |
|
4960 |
return 1; |
|
5003 |
helper_vmexit(type, param); |
|
4961 | 5004 |
} |
4962 | 5005 |
break; |
4963 | 5006 |
case SVM_EXIT_IOIO: |
4964 |
if (INTERCEPTED(1ULL << INTERCEPT_IOIO_PROT)) { |
|
4965 |
/* FIXME: this should be read in at vmrun (faster this way?) */ |
|
4966 |
uint64_t addr = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.iopm_base_pa)); |
|
4967 |
uint16_t port = (uint16_t) (param >> 16); |
|
4968 |
|
|
4969 |
uint16_t mask = (1 << ((param >> 4) & 7)) - 1; |
|
4970 |
if(lduw_phys(addr + port / 8) & (mask << (port & 7))) |
|
4971 |
vmexit(type, param); |
|
4972 |
} |
|
4973 | 5007 |
break; |
4974 | 5008 |
|
4975 | 5009 |
case SVM_EXIT_MSR: |
4976 | 5010 |
if (INTERCEPTED(1ULL << INTERCEPT_MSR_PROT)) { |
4977 | 5011 |
/* FIXME: this should be read in at vmrun (faster this way?) */ |
4978 | 5012 |
uint64_t addr = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.msrpm_base_pa)); |
5013 |
uint32_t t0, t1; |
|
4979 | 5014 |
switch((uint32_t)ECX) { |
4980 | 5015 |
case 0 ... 0x1fff: |
4981 |
T0 = (ECX * 2) % 8;
|
|
4982 |
T1 = ECX / 8;
|
|
5016 |
t0 = (ECX * 2) % 8;
|
|
5017 |
t1 = ECX / 8;
|
|
4983 | 5018 |
break; |
4984 | 5019 |
case 0xc0000000 ... 0xc0001fff: |
4985 |
T0 = (8192 + ECX - 0xc0000000) * 2;
|
|
4986 |
T1 = (T0 / 8);
|
|
4987 |
T0 %= 8;
|
|
5020 |
t0 = (8192 + ECX - 0xc0000000) * 2;
|
|
5021 |
t1 = (t0 / 8);
|
|
5022 |
t0 %= 8;
|
|
4988 | 5023 |
break; |
4989 | 5024 |
case 0xc0010000 ... 0xc0011fff: |
4990 |
T0 = (16384 + ECX - 0xc0010000) * 2;
|
|
4991 |
T1 = (T0 / 8);
|
|
4992 |
T0 %= 8;
|
|
5025 |
t0 = (16384 + ECX - 0xc0010000) * 2;
|
|
5026 |
t1 = (t0 / 8);
|
|
5027 |
t0 %= 8;
|
|
4993 | 5028 |
break; |
4994 | 5029 |
default: |
4995 |
vmexit(type, param); |
|
4996 |
return 1; |
|
5030 |
helper_vmexit(type, param); |
|
5031 |
t0 = 0; |
|
5032 |
t1 = 0; |
|
5033 |
break; |
|
4997 | 5034 |
} |
4998 |
if (ldub_phys(addr + T1) & ((1 << param) << T0)) |
|
4999 |
vmexit(type, param); |
|
5000 |
return 1; |
|
5035 |
if (ldub_phys(addr + t1) & ((1 << param) << t0)) |
|
5036 |
helper_vmexit(type, param); |
|
5001 | 5037 |
} |
5002 | 5038 |
break; |
5003 | 5039 |
default: |
5004 | 5040 |
if (INTERCEPTED((1ULL << ((type - SVM_EXIT_INTR) + INTERCEPT_INTR)))) { |
5005 |
vmexit(type, param); |
|
5006 |
return 1; |
|
5041 |
helper_vmexit(type, param); |
|
5007 | 5042 |
} |
5008 | 5043 |
break; |
5009 | 5044 |
} |
5010 |
return 0; |
|
5011 | 5045 |
} |
5012 | 5046 |
|
5013 |
void vmexit(uint64_t exit_code, uint64_t exit_info_1) |
|
5047 |
void helper_svm_check_io(uint32_t port, uint32_t param, |
|
5048 |
uint32_t next_eip_addend) |
|
5049 |
{ |
|
5050 |
if (INTERCEPTED(1ULL << INTERCEPT_IOIO_PROT)) { |
|
5051 |
/* FIXME: this should be read in at vmrun (faster this way?) */ |
|
5052 |
uint64_t addr = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.iopm_base_pa)); |
|
5053 |
uint16_t mask = (1 << ((param >> 4) & 7)) - 1; |
|
5054 |
if(lduw_phys(addr + port / 8) & (mask << (port & 7))) { |
|
5055 |
/* next EIP */ |
|
5056 |
stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2), |
|
5057 |
env->eip + next_eip_addend); |
|
5058 |
helper_vmexit(SVM_EXIT_IOIO, param | (port << 16)); |
|
5059 |
} |
|
5060 |
} |
|
5061 |
} |
|
5062 |
|
|
5063 |
/* Note: currently only 32 bits of exit_code are used */ |
|
5064 |
void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1) |
|
5014 | 5065 |
{ |
5015 | 5066 |
uint32_t int_ctl; |
5016 | 5067 |
|
5017 | 5068 |
if (loglevel & CPU_LOG_TB_IN_ASM) |
5018 |
fprintf(logfile,"vmexit(%016" PRIx64 ", %016" PRIx64 ", %016" PRIx64 ", " TARGET_FMT_lx ")!\n",
|
|
5069 |
fprintf(logfile,"vmexit(%08x, %016" PRIx64 ", %016" PRIx64 ", " TARGET_FMT_lx ")!\n",
|
|
5019 | 5070 |
exit_code, exit_info_1, |
5020 | 5071 |
ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2)), |
5021 | 5072 |
EIP); |
... | ... | |
5105 | 5156 |
|
5106 | 5157 |
/* other setups */ |
5107 | 5158 |
cpu_x86_set_cpl(env, 0); |
5108 |
stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_code_hi), (uint32_t)(exit_code >> 32)); |
|
5109 |
stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_code), exit_code); |
|
5159 |
stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_code), exit_code); |
|
5110 | 5160 |
stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_1), exit_info_1); |
5111 | 5161 |
|
5112 | 5162 |
helper_clgi(); |
... | ... | |
5137 | 5187 |
env->error_code = 0; |
5138 | 5188 |
env->old_exception = -1; |
5139 | 5189 |
|
5140 |
regs_to_env(); |
|
5141 | 5190 |
cpu_loop_exit(); |
5142 | 5191 |
} |
5143 | 5192 |
|
Also available in: Unified diff