diff options
author | Keir Fraser <keir.fraser@citrix.com> | 2009-08-19 13:02:31 +0100 |
---|---|---|
committer | Keir Fraser <keir.fraser@citrix.com> | 2009-08-19 13:02:31 +0100 |
commit | c88b1e06d5ad6d24b5cb0cb6f80ae35d94002ef5 (patch) | |
tree | a3e3c997f1f342b00d1e890b5627554e5cdf1e85 | |
parent | b2c296e1c5dcbcca103b5fcc3862de8a3faa99c3 (diff) | |
download | xen-c88b1e06d5ad6d24b5cb0cb6f80ae35d94002ef5.tar.gz xen-c88b1e06d5ad6d24b5cb0cb6f80ae35d94002ef5.tar.bz2 xen-c88b1e06d5ad6d24b5cb0cb6f80ae35d94002ef5.zip |
x86: miscellaneous emulator adjustments
Defer fail_if()-s as much as possible (in favor of possibly generating
exceptions), and avoid generating exceptions when not strictly
necessary.
Avoid fail_if()-s for simple return code checks (making the code that
used them consistent with other, longer existing code).
Eliminate redundant generate_exception_if()-s checking lock_prefix
(which is already covered by the general check prior to decoding
operands).
Also fix the testing code to add PROT_EXEC for the mapping that is
intended to have instruction executed from.
Signed-off-by: Jan Beulich <jbeulich@novell.com>
-rw-r--r-- | tools/tests/test_x86_emulator.c | 2 | ||||
-rw-r--r-- | xen/arch/x86/x86_emulate/x86_emulate.c | 88 |
2 files changed, 40 insertions, 50 deletions
diff --git a/tools/tests/test_x86_emulator.c b/tools/tests/test_x86_emulator.c index 4215686888..dca401f93d 100644 --- a/tools/tests/test_x86_emulator.c +++ b/tools/tests/test_x86_emulator.c @@ -76,7 +76,7 @@ int main(int argc, char **argv) ctxt.addr_size = 32; ctxt.sp_size = 32; - res = mmap((void *)0x100000, MMAP_SZ, PROT_READ|PROT_WRITE, + res = mmap((void *)0x100000, MMAP_SZ, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); if ( res == MAP_FAILED ) { diff --git a/xen/arch/x86/x86_emulate/x86_emulate.c b/xen/arch/x86/x86_emulate/x86_emulate.c index 5872fe942a..5f8361e2b2 100644 --- a/xen/arch/x86/x86_emulate/x86_emulate.c +++ b/xen/arch/x86/x86_emulate/x86_emulate.c @@ -3583,21 +3583,17 @@ x86_emulate( struct segment_register cs = { 0 }, ss = { 0 }; int rc; - fail_if(ops->read_msr == NULL); - fail_if(ops->read_segment == NULL); - fail_if(ops->write_segment == NULL); - generate_exception_if(in_realmode(ctxt, ops), EXC_UD, 0); generate_exception_if(!in_protmode(ctxt, ops), EXC_UD, 0); - generate_exception_if(lock_prefix, EXC_UD, 0); /* Inject #UD if syscall/sysret are disabled. */ - rc = ops->read_msr(MSR_EFER, &msr_content, ctxt); - fail_if(rc != 0); + fail_if(ops->read_msr == NULL); + if ( (rc = ops->read_msr(MSR_EFER, &msr_content, ctxt)) != 0 ) + goto done; generate_exception_if((msr_content & EFER_SCE) == 0, EXC_UD, 0); - rc = ops->read_msr(MSR_STAR, &msr_content, ctxt); - fail_if(rc != 0); + if ( (rc = ops->read_msr(MSR_STAR, &msr_content, ctxt)) != 0 ) + goto done; msr_content >>= 32; cs.sel = (uint16_t)(msr_content & 0xfffc); @@ -3617,27 +3613,27 @@ x86_emulate( _regs.rcx = _regs.rip; _regs.r11 = _regs.eflags & ~EFLG_RF; - rc = ops->read_msr(mode_64bit() ? MSR_LSTAR : MSR_CSTAR, - &msr_content, ctxt); - fail_if(rc != 0); - + if ( (rc = ops->read_msr(mode_64bit() ? MSR_LSTAR : MSR_CSTAR, + &msr_content, ctxt)) != 0 ) + goto done; _regs.rip = msr_content; - rc = ops->read_msr(MSR_FMASK, &msr_content, ctxt); - fail_if(rc != 0); + if ( (rc = ops->read_msr(MSR_FMASK, &msr_content, ctxt)) != 0 ) + goto done; _regs.eflags &= ~(msr_content | EFLG_RF); } else #endif { - rc = ops->read_msr(MSR_STAR, &msr_content, ctxt); - fail_if(rc != 0); + if ( (rc = ops->read_msr(MSR_STAR, &msr_content, ctxt)) != 0 ) + goto done; _regs.ecx = _regs.eip; _regs.eip = (uint32_t)msr_content; _regs.eflags &= ~(EFLG_VM | EFLG_IF | EFLG_RF); } + fail_if(ops->write_segment == NULL); if ( (rc = ops->write_segment(x86_seg_cs, &cs, ctxt)) || (rc = ops->write_segment(x86_seg_ss, &ss, ctxt)) ) goto done; @@ -3717,10 +3713,13 @@ x86_emulate( case 0x31: /* rdtsc */ { unsigned long cr4; uint64_t val; - fail_if(ops->read_cr == NULL); - if ( (rc = ops->read_cr(4, &cr4, ctxt)) ) - goto done; - generate_exception_if((cr4 & CR4_TSD) && !mode_ring0(), EXC_GP, 0); + if ( !mode_ring0() ) + { + fail_if(ops->read_cr == NULL); + if ( (rc = ops->read_cr(4, &cr4, ctxt)) ) + goto done; + generate_exception_if(cr4 & CR4_TSD, EXC_GP, 0); + } fail_if(ops->read_msr == NULL); if ( (rc = ops->read_msr(MSR_TSC, &val, ctxt)) != 0 ) goto done; @@ -3751,17 +3750,13 @@ x86_emulate( struct segment_register cs, ss; int rc; - fail_if(ops->read_msr == NULL); - fail_if(ops->read_segment == NULL); - fail_if(ops->write_segment == NULL); - generate_exception_if(mode_ring0(), EXC_GP, 0); generate_exception_if(in_realmode(ctxt, ops), EXC_GP, 0); generate_exception_if(!in_protmode(ctxt, ops), EXC_GP, 0); - generate_exception_if(lock_prefix, EXC_UD, 0); - rc = ops->read_msr(MSR_SYSENTER_CS, &msr_content, ctxt); - fail_if(rc != 0); + fail_if(ops->read_msr == NULL); + if ( (rc = ops->read_msr(MSR_SYSENTER_CS, &msr_content, ctxt)) != 0 ) + goto done; if ( mode_64bit() ) generate_exception_if(msr_content == 0, EXC_GP, 0); @@ -3770,6 +3765,7 @@ x86_emulate( _regs.eflags &= ~(EFLG_VM | EFLG_IF | EFLG_RF); + fail_if(ops->read_segment == NULL); ops->read_segment(x86_seg_cs, &cs, ctxt); cs.sel = (uint16_t)msr_content & ~3; /* SELECTOR_RPL_MASK */ cs.base = 0; /* flat segment */ @@ -3787,17 +3783,17 @@ x86_emulate( cs.attr.fields.l = 1; } - rc = ops->write_segment(x86_seg_cs, &cs, ctxt); - fail_if(rc != 0); - rc = ops->write_segment(x86_seg_ss, &ss, ctxt); - fail_if(rc != 0); + fail_if(ops->write_segment == NULL); + if ( (rc = ops->write_segment(x86_seg_cs, &cs, ctxt)) != 0 || + (rc = ops->write_segment(x86_seg_ss, &ss, ctxt)) != 0 ) + goto done; - rc = ops->read_msr(MSR_SYSENTER_EIP, &msr_content, ctxt); - fail_if(rc != 0); + if ( (rc = ops->read_msr(MSR_SYSENTER_EIP, &msr_content, ctxt)) != 0 ) + goto done; _regs.eip = msr_content; - rc = ops->read_msr(MSR_SYSENTER_ESP, &msr_content, ctxt); - fail_if(rc != 0); + if ( (rc = ops->read_msr(MSR_SYSENTER_ESP, &msr_content, ctxt)) != 0 ) + goto done; _regs.esp = msr_content; break; @@ -3809,19 +3805,13 @@ x86_emulate( int user64 = !!(rex_prefix & 8); /* REX.W */ int rc; - fail_if(ops->read_msr == NULL); - fail_if(ops->read_segment == NULL); - fail_if(ops->write_segment == NULL); - generate_exception_if(!mode_ring0(), EXC_GP, 0); generate_exception_if(in_realmode(ctxt, ops), EXC_GP, 0); generate_exception_if(!in_protmode(ctxt, ops), EXC_GP, 0); - generate_exception_if(lock_prefix, EXC_UD, 0); - rc = ops->read_msr(MSR_SYSENTER_CS, &msr_content, ctxt); - fail_if(rc != 0); - rc = ops->read_segment(x86_seg_cs, &cs, ctxt); - fail_if(rc != 0); + fail_if(ops->read_msr == NULL); + if ( (rc = ops->read_msr(MSR_SYSENTER_CS, &msr_content, ctxt)) != 0 ) + goto done; if ( user64 ) { @@ -3852,10 +3842,10 @@ x86_emulate( cs.attr.fields.l = 1; } - rc = ops->write_segment(x86_seg_cs, &cs, ctxt); - fail_if(rc != 0); - rc = ops->write_segment(x86_seg_ss, &ss, ctxt); - fail_if(rc != 0); + fail_if(ops->write_segment == NULL); + if ( (rc = ops->write_segment(x86_seg_cs, &cs, ctxt)) != 0 || + (rc = ops->write_segment(x86_seg_ss, &ss, ctxt)) != 0 ) + goto done; _regs.eip = _regs.edx; _regs.esp = _regs.ecx; |