aboutsummaryrefslogtreecommitdiffstats
path: root/xen/arch/x86/x86_emulate.c
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2007-11-26 17:54:54 +0000
committerKeir Fraser <keir.fraser@citrix.com>2007-11-26 17:54:54 +0000
commit70d9b1077f1a4586092851badeca60703b57eccf (patch)
treeb2c658c67ebe08114b2d6b30ae25eaf66a72e4f7 /xen/arch/x86/x86_emulate.c
parenta209260781bec2fa050c0ed9f38171373e8d81a2 (diff)
downloadxen-70d9b1077f1a4586092851badeca60703b57eccf.tar.gz
xen-70d9b1077f1a4586092851badeca60703b57eccf.tar.bz2
xen-70d9b1077f1a4586092851badeca60703b57eccf.zip
x86_emulate: Emulate LMSW and SMSW.
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
Diffstat (limited to 'xen/arch/x86/x86_emulate.c')
-rw-r--r--xen/arch/x86/x86_emulate.c31
1 files changed, 28 insertions, 3 deletions
diff --git a/xen/arch/x86/x86_emulate.c b/xen/arch/x86/x86_emulate.c
index 1397732a7f..763d73774f 100644
--- a/xen/arch/x86/x86_emulate.c
+++ b/xen/arch/x86/x86_emulate.c
@@ -2666,6 +2666,7 @@ x86_emulate(
{
case 0x01: /* Grp7 */ {
struct segment_register reg;
+ unsigned long base, limit, cr0, cr0w;
switch ( modrm_reg & 7 )
{
@@ -2691,11 +2692,12 @@ x86_emulate(
fail_if(ops->write_segment == NULL);
memset(&reg, 0, sizeof(reg));
if ( (rc = ops->read(ea.mem.seg, ea.mem.off+0,
- (unsigned long *)&reg.limit, 2, ctxt)) ||
+ &limit, 2, ctxt)) ||
(rc = ops->read(ea.mem.seg, ea.mem.off+2,
- (unsigned long *)&reg.base,
- mode_64bit() ? 8 : 4, ctxt)) )
+ &base, mode_64bit() ? 8 : 4, ctxt)) )
goto done;
+ reg.base = base;
+ reg.limit = limit;
if ( op_bytes == 2 )
reg.base &= 0xffffff;
if ( (rc = ops->write_segment((modrm_reg & 1) ?
@@ -2703,6 +2705,29 @@ x86_emulate(
&reg, ctxt)) )
goto done;
break;
+ case 4: /* smsw */
+ dst = ea;
+ dst.bytes = 2;
+ fail_if(ops->read_cr == NULL);
+ if ( (rc = ops->read_cr(0, &dst.val, ctxt)) )
+ goto done;
+ d |= Mov; /* force writeback */
+ break;
+ case 6: /* lmsw */
+ fail_if(ops->read_cr == NULL);
+ fail_if(ops->write_cr == NULL);
+ if ( (rc = ops->read_cr(0, &cr0, ctxt)) )
+ goto done;
+ if ( ea.type == OP_REG )
+ cr0w = *ea.reg;
+ else if ( (rc = ops->read(ea.mem.seg, ea.mem.off,
+ &cr0w, 2, ctxt)) )
+ goto done;
+ cr0 &= 0xffff0000;
+ cr0 |= (uint16_t)cr0w;
+ if ( (rc = ops->write_cr(0, cr0, ctxt)) )
+ goto done;
+ break;
default:
goto cannot_emulate;
}