debuggers.hg
changeset 16599:a74efcdc87b3
vmx realmode: Fix exception delivery w.r.t. in-flight I/O.
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author | Keir Fraser <keir.fraser@citrix.com> |
---|---|
date | Fri Dec 07 16:39:15 2007 +0000 (2007-12-07) |
parents | 822d4ec5cfb1 |
children | 35890b260971 |
files | xen/arch/x86/hvm/vmx/realmode.c |
line diff
1.1 --- a/xen/arch/x86/hvm/vmx/realmode.c Fri Dec 07 14:44:13 2007 +0000 1.2 +++ b/xen/arch/x86/hvm/vmx/realmode.c Fri Dec 07 16:39:15 2007 +0000 1.3 @@ -35,10 +35,12 @@ struct realmode_emulate_ctxt { 1.4 unsigned int hlt:1; 1.5 unsigned int mov_ss:1; 1.6 unsigned int sti:1; 1.7 - unsigned int exn_raised:1; 1.8 } flags; 1.9 unsigned int flag_word; 1.10 }; 1.11 + 1.12 + uint8_t exn_vector; 1.13 + uint8_t exn_insn_len; 1.14 }; 1.15 1.16 static void realmode_deliver_exception( 1.17 @@ -104,8 +106,7 @@ static void realmode_deliver_exception( 1.18 csr->sel = cs_eip >> 16; 1.19 csr->base = (uint32_t)csr->sel << 4; 1.20 regs->eip = (uint16_t)cs_eip; 1.21 - regs->eflags &= ~(X86_EFLAGS_AC | X86_EFLAGS_TF | 1.22 - X86_EFLAGS_AC | X86_EFLAGS_RF); 1.23 + regs->eflags &= ~(X86_EFLAGS_TF | X86_EFLAGS_IF | X86_EFLAGS_RF); 1.24 } 1.25 1.26 static int 1.27 @@ -145,7 +146,7 @@ realmode_read( 1.28 } 1.29 1.30 if ( !curr->arch.hvm_vmx.real_mode_io_completed ) 1.31 - return X86EMUL_UNHANDLEABLE; 1.32 + return X86EMUL_RETRY; 1.33 1.34 *val = curr->arch.hvm_vmx.real_mode_io_data; 1.35 curr->arch.hvm_vmx.real_mode_io_completed = 0; 1.36 @@ -286,7 +287,7 @@ realmode_read_io( 1.37 } 1.38 1.39 if ( !curr->arch.hvm_vmx.real_mode_io_completed ) 1.40 - return X86EMUL_UNHANDLEABLE; 1.41 + return X86EMUL_RETRY; 1.42 1.43 *val = curr->arch.hvm_vmx.real_mode_io_data; 1.44 curr->arch.hvm_vmx.real_mode_io_completed = 0; 1.45 @@ -413,8 +414,8 @@ static int realmode_inject_hw_exception( 1.46 struct realmode_emulate_ctxt *rm_ctxt = 1.47 container_of(ctxt, struct realmode_emulate_ctxt, ctxt); 1.48 1.49 - rm_ctxt->flags.exn_raised = 1; 1.50 - realmode_deliver_exception(vector, 0, rm_ctxt); 1.51 + rm_ctxt->exn_vector = vector; 1.52 + rm_ctxt->exn_insn_len = 0; 1.53 1.54 return X86EMUL_OKAY; 1.55 } 1.56 @@ -427,7 +428,8 @@ static int realmode_inject_sw_interrupt( 1.57 struct realmode_emulate_ctxt *rm_ctxt = 1.58 container_of(ctxt, struct realmode_emulate_ctxt, ctxt); 1.59 1.60 - realmode_deliver_exception(vector, insn_len, rm_ctxt); 1.61 + rm_ctxt->exn_vector = vector; 1.62 + rm_ctxt->exn_insn_len = insn_len; 1.63 1.64 return X86EMUL_OKAY; 1.65 } 1.66 @@ -470,19 +472,22 @@ void vmx_realmode(struct cpu_user_regs * 1.67 rm_ctxt.seg_reg[x86_seg_ss].attr.fields.db ? 32 : 16; 1.68 1.69 intr_info = __vmread(VM_ENTRY_INTR_INFO); 1.70 - if ( intr_info & INTR_INFO_VALID_MASK ) 1.71 - { 1.72 - __vmwrite(VM_ENTRY_INTR_INFO, 0); 1.73 - realmode_deliver_exception((uint8_t)intr_info, 0, &rm_ctxt); 1.74 - } 1.75 - 1.76 intr_shadow = __vmread(GUEST_INTERRUPTIBILITY_INFO); 1.77 new_intr_shadow = intr_shadow; 1.78 1.79 while ( !(curr->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PE) && 1.80 !softirq_pending(smp_processor_id()) && 1.81 - !hvm_local_events_need_delivery(curr) ) 1.82 + !hvm_local_events_need_delivery(curr) && 1.83 + !curr->arch.hvm_vmx.real_mode_io_in_progress ) 1.84 { 1.85 + if ( (intr_info & INTR_INFO_VALID_MASK) && 1.86 + !curr->arch.hvm_vmx.real_mode_io_completed ) 1.87 + { 1.88 + realmode_deliver_exception((uint8_t)intr_info, 0, &rm_ctxt); 1.89 + __vmwrite(VM_ENTRY_INTR_INFO, 0); 1.90 + intr_info = 0; 1.91 + } 1.92 + 1.93 rm_ctxt.insn_buf_eip = regs->eip; 1.94 (void)hvm_copy_from_guest_phys( 1.95 rm_ctxt.insn_buf, 1.96 @@ -493,6 +498,21 @@ void vmx_realmode(struct cpu_user_regs * 1.97 1.98 rc = x86_emulate(&rm_ctxt.ctxt, &realmode_emulator_ops); 1.99 1.100 + if ( rc == X86EMUL_RETRY ) 1.101 + continue; 1.102 + 1.103 + if ( rc == X86EMUL_UNHANDLEABLE ) 1.104 + { 1.105 + gdprintk(XENLOG_ERR, 1.106 + "Real-mode emulation failed @ %04x:%08lx: " 1.107 + "%02x %02x %02x %02x %02x %02x\n", 1.108 + rm_ctxt.seg_reg[x86_seg_cs].sel, rm_ctxt.insn_buf_eip, 1.109 + rm_ctxt.insn_buf[0], rm_ctxt.insn_buf[1], 1.110 + rm_ctxt.insn_buf[2], rm_ctxt.insn_buf[3], 1.111 + rm_ctxt.insn_buf[4], rm_ctxt.insn_buf[5]); 1.112 + domain_crash_synchronous(); 1.113 + } 1.114 + 1.115 /* MOV-SS instruction toggles MOV-SS shadow, else we just clear it. */ 1.116 if ( rm_ctxt.flags.mov_ss ) 1.117 new_intr_shadow ^= VMX_INTR_SHADOW_MOV_SS; 1.118 @@ -512,25 +532,14 @@ void vmx_realmode(struct cpu_user_regs * 1.119 __vmwrite(GUEST_INTERRUPTIBILITY_INFO, intr_shadow); 1.120 } 1.121 1.122 - /* HLT happens after instruction retire, if no interrupt/exception. */ 1.123 - if ( unlikely(rm_ctxt.flags.hlt) && 1.124 - !rm_ctxt.flags.exn_raised && 1.125 - !hvm_local_events_need_delivery(curr) ) 1.126 + if ( rc == X86EMUL_EXCEPTION ) 1.127 + { 1.128 + realmode_deliver_exception( 1.129 + rm_ctxt.exn_vector, rm_ctxt.exn_insn_len, &rm_ctxt); 1.130 + } 1.131 + else if ( rm_ctxt.flags.hlt && !hvm_local_events_need_delivery(curr) ) 1.132 + { 1.133 hvm_hlt(regs->eflags); 1.134 - 1.135 - if ( curr->arch.hvm_vmx.real_mode_io_in_progress ) 1.136 - break; 1.137 - 1.138 - if ( rc == X86EMUL_UNHANDLEABLE ) 1.139 - { 1.140 - gdprintk(XENLOG_ERR, 1.141 - "Real-mode emulation failed @ %04x:%08lx: " 1.142 - "%02x %02x %02x %02x %02x %02x\n", 1.143 - rm_ctxt.seg_reg[x86_seg_cs].sel, rm_ctxt.insn_buf_eip, 1.144 - rm_ctxt.insn_buf[0], rm_ctxt.insn_buf[1], 1.145 - rm_ctxt.insn_buf[2], rm_ctxt.insn_buf[3], 1.146 - rm_ctxt.insn_buf[4], rm_ctxt.insn_buf[5]); 1.147 - domain_crash_synchronous(); 1.148 } 1.149 } 1.150