Commit 3d7374c5dab5670891e34d6f5752d6c3e23259dc
1 parent
4f209290
monitor/mwait support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2044 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
4 changed files
with
97 additions
and
14 deletions
target-i386/exec.h
| @@ -496,6 +496,9 @@ void save_native_fp_state(CPUState *env); | @@ -496,6 +496,9 @@ void save_native_fp_state(CPUState *env); | ||
| 496 | float approx_rsqrt(float a); | 496 | float approx_rsqrt(float a); |
| 497 | float approx_rcp(float a); | 497 | float approx_rcp(float a); |
| 498 | void update_fp_status(void); | 498 | void update_fp_status(void); |
| 499 | +void helper_hlt(void); | ||
| 500 | +void helper_monitor(void); | ||
| 501 | +void helper_mwait(void); | ||
| 499 | 502 | ||
| 500 | extern const uint8_t parity_table[256]; | 503 | extern const uint8_t parity_table[256]; |
| 501 | extern const uint8_t rclw_table[32]; | 504 | extern const uint8_t rclw_table[32]; |
target-i386/helper.c
| @@ -3408,6 +3408,34 @@ void helper_bswapq_T0(void) | @@ -3408,6 +3408,34 @@ void helper_bswapq_T0(void) | ||
| 3408 | } | 3408 | } |
| 3409 | #endif | 3409 | #endif |
| 3410 | 3410 | ||
| 3411 | +void helper_hlt(void) | ||
| 3412 | +{ | ||
| 3413 | + env->hflags &= ~HF_INHIBIT_IRQ_MASK; /* needed if sti is just before */ | ||
| 3414 | + env->hflags |= HF_HALTED_MASK; | ||
| 3415 | + env->exception_index = EXCP_HLT; | ||
| 3416 | + cpu_loop_exit(); | ||
| 3417 | +} | ||
| 3418 | + | ||
| 3419 | +void helper_monitor(void) | ||
| 3420 | +{ | ||
| 3421 | + if (ECX != 0) | ||
| 3422 | + raise_exception(EXCP0D_GPF); | ||
| 3423 | + /* XXX: store address ? */ | ||
| 3424 | +} | ||
| 3425 | + | ||
| 3426 | +void helper_mwait(void) | ||
| 3427 | +{ | ||
| 3428 | + if (ECX != 0) | ||
| 3429 | + raise_exception(EXCP0D_GPF); | ||
| 3430 | + /* XXX: not complete but not completely erroneous */ | ||
| 3431 | + if (env->cpu_index != 0 || env->next_cpu != NULL) { | ||
| 3432 | + /* more than one CPU: do not sleep because another CPU may | ||
| 3433 | + wake this one */ | ||
| 3434 | + } else { | ||
| 3435 | + helper_hlt(); | ||
| 3436 | + } | ||
| 3437 | +} | ||
| 3438 | + | ||
| 3411 | float approx_rsqrt(float a) | 3439 | float approx_rsqrt(float a) |
| 3412 | { | 3440 | { |
| 3413 | return 1.0 / sqrt(a); | 3441 | return 1.0 / sqrt(a); |
target-i386/op.c
| @@ -614,10 +614,17 @@ void OPPROTO op_movq_eip_im64(void) | @@ -614,10 +614,17 @@ void OPPROTO op_movq_eip_im64(void) | ||
| 614 | 614 | ||
| 615 | void OPPROTO op_hlt(void) | 615 | void OPPROTO op_hlt(void) |
| 616 | { | 616 | { |
| 617 | - env->hflags &= ~HF_INHIBIT_IRQ_MASK; /* needed if sti is just before */ | ||
| 618 | - env->hflags |= HF_HALTED_MASK; | ||
| 619 | - env->exception_index = EXCP_HLT; | ||
| 620 | - cpu_loop_exit(); | 617 | + helper_hlt(); |
| 618 | +} | ||
| 619 | + | ||
| 620 | +void OPPROTO op_monitor(void) | ||
| 621 | +{ | ||
| 622 | + helper_monitor(); | ||
| 623 | +} | ||
| 624 | + | ||
| 625 | +void OPPROTO op_mwait(void) | ||
| 626 | +{ | ||
| 627 | + helper_mwait(); | ||
| 621 | } | 628 | } |
| 622 | 629 | ||
| 623 | void OPPROTO op_debug(void) | 630 | void OPPROTO op_debug(void) |
target-i386/translate.c
| @@ -100,6 +100,7 @@ typedef struct DisasContext { | @@ -100,6 +100,7 @@ typedef struct DisasContext { | ||
| 100 | int popl_esp_hack; /* for correct popl with esp base handling */ | 100 | int popl_esp_hack; /* for correct popl with esp base handling */ |
| 101 | int rip_offset; /* only used in x86_64, but left for simplicity */ | 101 | int rip_offset; /* only used in x86_64, but left for simplicity */ |
| 102 | int cpuid_features; | 102 | int cpuid_features; |
| 103 | + int cpuid_ext_features; | ||
| 103 | } DisasContext; | 104 | } DisasContext; |
| 104 | 105 | ||
| 105 | static void gen_eob(DisasContext *s); | 106 | static void gen_eob(DisasContext *s); |
| @@ -5567,26 +5568,69 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | @@ -5567,26 +5568,69 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | ||
| 5567 | modrm = ldub_code(s->pc++); | 5568 | modrm = ldub_code(s->pc++); |
| 5568 | mod = (modrm >> 6) & 3; | 5569 | mod = (modrm >> 6) & 3; |
| 5569 | op = (modrm >> 3) & 7; | 5570 | op = (modrm >> 3) & 7; |
| 5571 | + rm = modrm & 7; | ||
| 5570 | switch(op) { | 5572 | switch(op) { |
| 5571 | case 0: /* sgdt */ | 5573 | case 0: /* sgdt */ |
| 5572 | - case 1: /* sidt */ | ||
| 5573 | if (mod == 3) | 5574 | if (mod == 3) |
| 5574 | goto illegal_op; | 5575 | goto illegal_op; |
| 5575 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); | 5576 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
| 5576 | - if (op == 0) | ||
| 5577 | - gen_op_movl_T0_env(offsetof(CPUX86State,gdt.limit)); | ||
| 5578 | - else | ||
| 5579 | - gen_op_movl_T0_env(offsetof(CPUX86State,idt.limit)); | 5577 | + gen_op_movl_T0_env(offsetof(CPUX86State, gdt.limit)); |
| 5580 | gen_op_st_T0_A0[OT_WORD + s->mem_index](); | 5578 | gen_op_st_T0_A0[OT_WORD + s->mem_index](); |
| 5581 | gen_add_A0_im(s, 2); | 5579 | gen_add_A0_im(s, 2); |
| 5582 | - if (op == 0) | ||
| 5583 | - gen_op_movtl_T0_env(offsetof(CPUX86State,gdt.base)); | ||
| 5584 | - else | ||
| 5585 | - gen_op_movtl_T0_env(offsetof(CPUX86State,idt.base)); | 5580 | + gen_op_movtl_T0_env(offsetof(CPUX86State, gdt.base)); |
| 5586 | if (!s->dflag) | 5581 | if (!s->dflag) |
| 5587 | gen_op_andl_T0_im(0xffffff); | 5582 | gen_op_andl_T0_im(0xffffff); |
| 5588 | gen_op_st_T0_A0[CODE64(s) + OT_LONG + s->mem_index](); | 5583 | gen_op_st_T0_A0[CODE64(s) + OT_LONG + s->mem_index](); |
| 5589 | break; | 5584 | break; |
| 5585 | + case 1: | ||
| 5586 | + if (mod == 3) { | ||
| 5587 | + switch (rm) { | ||
| 5588 | + case 0: /* monitor */ | ||
| 5589 | + if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) || | ||
| 5590 | + s->cpl != 0) | ||
| 5591 | + goto illegal_op; | ||
| 5592 | + gen_jmp_im(pc_start - s->cs_base); | ||
| 5593 | +#ifdef TARGET_X86_64 | ||
| 5594 | + if (s->aflag == 2) { | ||
| 5595 | + gen_op_movq_A0_reg[R_EBX](); | ||
| 5596 | + gen_op_addq_A0_AL(); | ||
| 5597 | + } else | ||
| 5598 | +#endif | ||
| 5599 | + { | ||
| 5600 | + gen_op_movl_A0_reg[R_EBX](); | ||
| 5601 | + gen_op_addl_A0_AL(); | ||
| 5602 | + if (s->aflag == 0) | ||
| 5603 | + gen_op_andl_A0_ffff(); | ||
| 5604 | + } | ||
| 5605 | + gen_add_A0_ds_seg(s); | ||
| 5606 | + gen_op_monitor(); | ||
| 5607 | + break; | ||
| 5608 | + case 1: /* mwait */ | ||
| 5609 | + if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) || | ||
| 5610 | + s->cpl != 0) | ||
| 5611 | + goto illegal_op; | ||
| 5612 | + if (s->cc_op != CC_OP_DYNAMIC) { | ||
| 5613 | + gen_op_set_cc_op(s->cc_op); | ||
| 5614 | + s->cc_op = CC_OP_DYNAMIC; | ||
| 5615 | + } | ||
| 5616 | + gen_jmp_im(s->pc - s->cs_base); | ||
| 5617 | + gen_op_mwait(); | ||
| 5618 | + gen_eob(s); | ||
| 5619 | + break; | ||
| 5620 | + default: | ||
| 5621 | + goto illegal_op; | ||
| 5622 | + } | ||
| 5623 | + } else { /* sidt */ | ||
| 5624 | + gen_lea_modrm(s, modrm, ®_addr, &offset_addr); | ||
| 5625 | + gen_op_movl_T0_env(offsetof(CPUX86State, idt.limit)); | ||
| 5626 | + gen_op_st_T0_A0[OT_WORD + s->mem_index](); | ||
| 5627 | + gen_add_A0_im(s, 2); | ||
| 5628 | + gen_op_movtl_T0_env(offsetof(CPUX86State, idt.base)); | ||
| 5629 | + if (!s->dflag) | ||
| 5630 | + gen_op_andl_T0_im(0xffffff); | ||
| 5631 | + gen_op_st_T0_A0[CODE64(s) + OT_LONG + s->mem_index](); | ||
| 5632 | + } | ||
| 5633 | + break; | ||
| 5590 | case 2: /* lgdt */ | 5634 | case 2: /* lgdt */ |
| 5591 | case 3: /* lidt */ | 5635 | case 3: /* lidt */ |
| 5592 | if (mod == 3) | 5636 | if (mod == 3) |
| @@ -5629,7 +5673,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | @@ -5629,7 +5673,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | ||
| 5629 | } else { | 5673 | } else { |
| 5630 | if (mod == 3) { | 5674 | if (mod == 3) { |
| 5631 | #ifdef TARGET_X86_64 | 5675 | #ifdef TARGET_X86_64 |
| 5632 | - if (CODE64(s) && (modrm & 7) == 0) { | 5676 | + if (CODE64(s) && rm == 0) { |
| 5633 | /* swapgs */ | 5677 | /* swapgs */ |
| 5634 | gen_op_movtl_T0_env(offsetof(CPUX86State,segs[R_GS].base)); | 5678 | gen_op_movtl_T0_env(offsetof(CPUX86State,segs[R_GS].base)); |
| 5635 | gen_op_movtl_T1_env(offsetof(CPUX86State,kernelgsbase)); | 5679 | gen_op_movtl_T1_env(offsetof(CPUX86State,kernelgsbase)); |
| @@ -6348,6 +6392,7 @@ static inline int gen_intermediate_code_internal(CPUState *env, | @@ -6348,6 +6392,7 @@ static inline int gen_intermediate_code_internal(CPUState *env, | ||
| 6348 | dc->mem_index = 1 * 4; | 6392 | dc->mem_index = 1 * 4; |
| 6349 | } | 6393 | } |
| 6350 | dc->cpuid_features = env->cpuid_features; | 6394 | dc->cpuid_features = env->cpuid_features; |
| 6395 | + dc->cpuid_ext_features = env->cpuid_ext_features; | ||
| 6351 | #ifdef TARGET_X86_64 | 6396 | #ifdef TARGET_X86_64 |
| 6352 | dc->lma = (flags >> HF_LMA_SHIFT) & 1; | 6397 | dc->lma = (flags >> HF_LMA_SHIFT) & 1; |
| 6353 | dc->code64 = (flags >> HF_CS64_SHIFT) & 1; | 6398 | dc->code64 = (flags >> HF_CS64_SHIFT) & 1; |