diff options
author | kaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk> | 2005-06-10 16:15:35 +0000 |
---|---|---|
committer | kaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk> | 2005-06-10 16:15:35 +0000 |
commit | 6a3e7b20356fdd77466caf5e439cf8261b9fbaf2 (patch) | |
tree | 0da0aec45cd807685397a4b8fb7fabb6800d7192 | |
parent | f88b78b9b6e33ec4e8d2afdabd4bc046e97b2ee9 (diff) | |
download | xen-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.c | 45 |
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 = ®s->cs; - break; case 0x3e: /* DS override */ - pseg = ®s->ds; - break; case 0x26: /* ES override */ - pseg = ®s->es; - break; case 0x64: /* FS override */ - pseg = ®s->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 = ®s->gs; - break; - case 0x36: /* SS override */ - pseg = ®s->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 = ®s->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) ? ®s->ss : ®s->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) ? ®s->ss : ®s->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! */ |