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 | 496 | float approx_rsqrt(float a); |
497 | 497 | float approx_rcp(float a); |
498 | 498 | void update_fp_status(void); |
499 | +void helper_hlt(void); | |
500 | +void helper_monitor(void); | |
501 | +void helper_mwait(void); | |
499 | 502 | |
500 | 503 | extern const uint8_t parity_table[256]; |
501 | 504 | extern const uint8_t rclw_table[32]; | ... | ... |
target-i386/helper.c
... | ... | @@ -3408,6 +3408,34 @@ void helper_bswapq_T0(void) |
3408 | 3408 | } |
3409 | 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 | 3439 | float approx_rsqrt(float a) |
3412 | 3440 | { |
3413 | 3441 | return 1.0 / sqrt(a); | ... | ... |
target-i386/op.c
... | ... | @@ -614,10 +614,17 @@ void OPPROTO op_movq_eip_im64(void) |
614 | 614 | |
615 | 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 | 630 | void OPPROTO op_debug(void) | ... | ... |
target-i386/translate.c
... | ... | @@ -100,6 +100,7 @@ typedef struct DisasContext { |
100 | 100 | int popl_esp_hack; /* for correct popl with esp base handling */ |
101 | 101 | int rip_offset; /* only used in x86_64, but left for simplicity */ |
102 | 102 | int cpuid_features; |
103 | + int cpuid_ext_features; | |
103 | 104 | } DisasContext; |
104 | 105 | |
105 | 106 | static void gen_eob(DisasContext *s); |
... | ... | @@ -5567,26 +5568,69 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
5567 | 5568 | modrm = ldub_code(s->pc++); |
5568 | 5569 | mod = (modrm >> 6) & 3; |
5569 | 5570 | op = (modrm >> 3) & 7; |
5571 | + rm = modrm & 7; | |
5570 | 5572 | switch(op) { |
5571 | 5573 | case 0: /* sgdt */ |
5572 | - case 1: /* sidt */ | |
5573 | 5574 | if (mod == 3) |
5574 | 5575 | goto illegal_op; |
5575 | 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 | 5578 | gen_op_st_T0_A0[OT_WORD + s->mem_index](); |
5581 | 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 | 5581 | if (!s->dflag) |
5587 | 5582 | gen_op_andl_T0_im(0xffffff); |
5588 | 5583 | gen_op_st_T0_A0[CODE64(s) + OT_LONG + s->mem_index](); |
5589 | 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 | 5634 | case 2: /* lgdt */ |
5591 | 5635 | case 3: /* lidt */ |
5592 | 5636 | if (mod == 3) |
... | ... | @@ -5629,7 +5673,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
5629 | 5673 | } else { |
5630 | 5674 | if (mod == 3) { |
5631 | 5675 | #ifdef TARGET_X86_64 |
5632 | - if (CODE64(s) && (modrm & 7) == 0) { | |
5676 | + if (CODE64(s) && rm == 0) { | |
5633 | 5677 | /* swapgs */ |
5634 | 5678 | gen_op_movtl_T0_env(offsetof(CPUX86State,segs[R_GS].base)); |
5635 | 5679 | gen_op_movtl_T1_env(offsetof(CPUX86State,kernelgsbase)); |
... | ... | @@ -6348,6 +6392,7 @@ static inline int gen_intermediate_code_internal(CPUState *env, |
6348 | 6392 | dc->mem_index = 1 * 4; |
6349 | 6393 | } |
6350 | 6394 | dc->cpuid_features = env->cpuid_features; |
6395 | + dc->cpuid_ext_features = env->cpuid_ext_features; | |
6351 | 6396 | #ifdef TARGET_X86_64 |
6352 | 6397 | dc->lma = (flags >> HF_LMA_SHIFT) & 1; |
6353 | 6398 | dc->code64 = (flags >> HF_CS64_SHIFT) & 1; | ... | ... |