aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>2005-06-10 16:15:35 +0000
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>2005-06-10 16:15:35 +0000
commit6a3e7b20356fdd77466caf5e439cf8261b9fbaf2 (patch)
tree0da0aec45cd807685397a4b8fb7fabb6800d7192
parentf88b78b9b6e33ec4e8d2afdabd4bc046e97b2ee9 (diff)
downloadxen-6a3e7b20356fdd77466caf5e439cf8261b9fbaf2.tar.gz
xen-6a3e7b20356fdd77466caf5e439cf8261b9fbaf2.tar.bz2
xen-6a3e7b20356fdd77466caf5e439cf8261b9fbaf2.zip
bitkeeper revision 1.1159.258.166 (42a9bca7SPmMRozAfET0WOMKS0VQZA)
Fix and simplify the seg_fixup code. It only needs to handle instructions with GS override. Signed-off-by: Keir Fraser <keir@xensource.com>
-rw-r--r--xen/arch/x86/x86_32/seg_fixup.c45
1 files changed, 18 insertions, 27 deletions
diff --git a/xen/arch/x86/x86_32/seg_fixup.c b/xen/arch/x86/x86_32/seg_fixup.c
index cc4a97c195..8a04f507d5 100644
--- a/xen/arch/x86/x86_32/seg_fixup.c
+++ b/xen/arch/x86/x86_32/seg_fixup.c
@@ -292,7 +292,7 @@ int gpf_emulate_4gb(struct xen_regs *regs)
u32 disp32 = 0;
u8 *eip; /* ptr to instruction start */
u8 *pb, b; /* ptr into instr. / current instr. byte */
- unsigned int *pseg = NULL; /* segment for memory operand (NULL=default) */
+ int gs_override = 0;
/* WARNING: We only work for ring-3 segments. */
if ( unlikely(VM86_MODE(regs)) || unlikely(!RING_3(regs)) )
@@ -325,30 +325,20 @@ int gpf_emulate_4gb(struct xen_regs *regs)
switch ( b )
{
case 0x67: /* Address-size override */
- DPRINTK("Unhandleable prefix byte %02x\n", b);
- goto fixme;
- case 0x66: /* Operand-size override */
- case 0xf0: /* LOCK */
- case 0xf2: /* REPNE/REPNZ */
- case 0xf3: /* REP/REPE/REPZ */
- break;
case 0x2e: /* CS override */
- pseg = &regs->cs;
- break;
case 0x3e: /* DS override */
- pseg = &regs->ds;
- break;
case 0x26: /* ES override */
- pseg = &regs->es;
- break;
case 0x64: /* FS override */
- pseg = &regs->fs;
+ case 0x36: /* SS override */
+ DPRINTK("Unhandled prefix %02x\n", b);
+ goto fail;
+ case 0x66: /* Operand-size override */
+ case 0xf0: /* LOCK */
+ case 0xf2: /* REPNE/REPNZ */
+ case 0xf3: /* REP/REPE/REPZ */
break;
case 0x65: /* GS override */
- pseg = &regs->gs;
- break;
- case 0x36: /* SS override */
- pseg = &regs->ss;
+ gs_override = 1;
break;
default: /* Not a prefix byte */
goto done_prefix;
@@ -356,6 +346,12 @@ int gpf_emulate_4gb(struct xen_regs *regs)
}
done_prefix:
+ if ( !gs_override )
+ {
+ DPRINTK("Only instructions with GS override\n");
+ goto fail;
+ }
+
decode = insn_decode[b]; /* opcode byte */
pb++;
if ( decode == 0 )
@@ -366,12 +362,13 @@ int gpf_emulate_4gb(struct xen_regs *regs)
if ( !(decode & HAS_MODRM) )
{
+ /* Must be a <disp32>, or bail. */
if ( (decode & 7) != 4 )
goto fail;
if ( get_user(offset, (u32 *)pb) )
{
- DPRINTK("Fault while extracting <disp8>.\n");
+ DPRINTK("Fault while extracting <disp32>.\n");
goto page_fault;
}
pb += 4;
@@ -409,8 +406,6 @@ int gpf_emulate_4gb(struct xen_regs *regs)
switch ( modrm >> 6 )
{
case 0:
- if ( pseg == NULL )
- pseg = &regs->ds;
disp32 = 0;
if ( rm == 5 ) /* disp32 rather than (EBP) */
{
@@ -425,8 +420,6 @@ int gpf_emulate_4gb(struct xen_regs *regs)
break;
case 1:
- if ( pseg == NULL ) /* NB. EBP defaults to SS */
- pseg = (rm == 5) ? &regs->ss : &regs->ds;
if ( get_user(disp8, pb) )
{
DPRINTK("Fault while extracting <disp8>.\n");
@@ -437,8 +430,6 @@ int gpf_emulate_4gb(struct xen_regs *regs)
break;
case 2:
- if ( pseg == NULL ) /* NB. EBP defaults to SS */
- pseg = (rm == 5) ? &regs->ss : &regs->ds;
if ( get_user(disp32, (u32 *)pb) )
{
DPRINTK("Fault while extracting <disp8>.\n");
@@ -457,7 +448,7 @@ int gpf_emulate_4gb(struct xen_regs *regs)
offset += *(u32 *)memreg;
skip_modrm:
- if ( !fixup_seg((u16)(*pseg), offset) )
+ if ( !fixup_seg((u16)regs->gs, offset) )
goto fail;
/* Success! */