Skip to content

Commit f60033d

Browse files
bonziniMichael Tokarev
authored andcommitted
target/i386: do not trigger IRQ shadow for LSS
Because LSS need not trigger an IRQ shadow, gen_movl_seg can't just use the destination register to decide whether to inhibit IRQs. Add an argument. Cc: [email protected] Signed-off-by: Paolo Bonzini <[email protected]> (cherry picked from commit e54ef98) (back-ported to 10.0) Signed-off-by: Michael Tokarev <[email protected]>
1 parent 01a9f1a commit f60033d

File tree

2 files changed

+22
-15
lines changed

2 files changed

+22
-15
lines changed

target/i386/tcg/emit.c.inc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,7 @@ static void gen_writeback(DisasContext *s, X86DecodedInsn *decode, int opn, TCGv
352352
break;
353353
case X86_OP_SEG:
354354
/* Note that gen_movl_seg takes care of interrupt shadow and TF. */
355-
gen_movl_seg(s, op->n, s->T0);
355+
gen_movl_seg(s, op->n, v, op->n == R_SS);
356356
break;
357357
case X86_OP_INT:
358358
if (op->has_ea) {
@@ -2372,7 +2372,7 @@ static void gen_lxx_seg(DisasContext *s, X86DecodedInsn *decode, int seg)
23722372
gen_op_ld_v(s, MO_16, s->T1, s->A0);
23732373

23742374
/* load the segment here to handle exceptions properly */
2375-
gen_movl_seg(s, seg, s->T1);
2375+
gen_movl_seg(s, seg, s->T1, false);
23762376
}
23772377

23782378
static void gen_LDS(DisasContext *s, X86DecodedInsn *decode)

target/i386/tcg/translate.c

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1992,25 +1992,32 @@ static void gen_op_movl_seg_real(DisasContext *s, X86Seg seg_reg, TCGv seg)
19921992

19931993
/* move SRC to seg_reg and compute if the CPU state may change. Never
19941994
call this function with seg_reg == R_CS */
1995-
static void gen_movl_seg(DisasContext *s, X86Seg seg_reg, TCGv src)
1995+
static void gen_movl_seg(DisasContext *s, X86Seg seg_reg, TCGv src, bool inhibit_irq)
19961996
{
19971997
if (PE(s) && !VM86(s)) {
1998-
tcg_gen_trunc_tl_i32(s->tmp2_i32, src);
1999-
gen_helper_load_seg(tcg_env, tcg_constant_i32(seg_reg), s->tmp2_i32);
2000-
/* abort translation because the addseg value may change or
2001-
because ss32 may change. For R_SS, translation must always
2002-
stop as a special handling must be done to disable hardware
2003-
interrupts for the next instruction */
2004-
if (seg_reg == R_SS) {
2005-
s->base.is_jmp = DISAS_EOB_INHIBIT_IRQ;
2006-
} else if (CODE32(s) && seg_reg < R_FS) {
1998+
TCGv_i32 sel = tcg_temp_new_i32();
1999+
2000+
tcg_gen_trunc_tl_i32(sel, src);
2001+
gen_helper_load_seg(tcg_env, tcg_constant_i32(seg_reg), sel);
2002+
2003+
/* For move to DS/ES/SS, the addseg or ss32 flags may change. */
2004+
if (CODE32(s) && seg_reg < R_FS) {
20072005
s->base.is_jmp = DISAS_EOB_NEXT;
20082006
}
20092007
} else {
20102008
gen_op_movl_seg_real(s, seg_reg, src);
2011-
if (seg_reg == R_SS) {
2012-
s->base.is_jmp = DISAS_EOB_INHIBIT_IRQ;
2013-
}
2009+
}
2010+
2011+
/*
2012+
* For MOV or POP to SS (but not LSS) translation must always
2013+
* stop as a special handling must be done to disable hardware
2014+
* interrupts for the next instruction.
2015+
*
2016+
* DISAS_EOB_INHIBIT_IRQ is a superset of DISAS_EOB_NEXT which
2017+
* might have been set above.
2018+
*/
2019+
if (inhibit_irq) {
2020+
s->base.is_jmp = DISAS_EOB_INHIBIT_IRQ;
20142021
}
20152022
}
20162023

0 commit comments

Comments
 (0)