In the x86 emu raised interrupt can be processed indefinitely over and over again under certain condition.

Bug #1041403 reported by Dmitry Klimenko
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
libx86 (Ubuntu)
New
Undecided
Unassigned

Bug Description

Here is interrupt handler in the decode.c file:

static void x86emu_intr_handle(void)
{
 u8 intno;

 if (M.x86.intr & INTR_SYNCH) {
  intno = M.x86.intno;
  if (_X86EMU_intrTab[intno]) {
   (*_X86EMU_intrTab[intno])(intno);
  } else {
   push_word((u16)M.x86.R_FLG);
   CLEAR_FLAG(F_IF);
   CLEAR_FLAG(F_TF);
   push_word(M.x86.R_CS);
   M.x86.R_CS = mem_access_word(intno * 4 + 2);
   push_word(M.x86.R_IP);
   M.x86.R_IP = mem_access_word(intno * 4);
   M.x86.intr = 0;
  }
 }
}

If execution goes in the first branch,
(_X86EMU_intrTab[intno]) {
   (*_X86EMU_intrTab[intno])(intno);

M.x86.intr flag is not cleared in the interrupt preparation function in the table ( file thunk.c ):

static void x86emu_do_int(int num)
{
 u32 eflags;

 /* fprintf(stderr, "Calling INT 0x%X (%04X:%04X)\n", num,
   (read_b((num << 2) + 3) << 8) + read_b((num << 2) + 2),
   (read_b((num << 2) + 1) << 8) + read_b((num << 2)));

 fprintf(stderr, " EAX is %X\n", (int) X86_EAX);
 */

 eflags = X86_EFLAGS;
 eflags = eflags | X86_IF_MASK;
 pushw(eflags);
 pushw(X86_CS);
 pushw(X86_IP);
 X86_EFLAGS = X86_EFLAGS & ~(X86_VIF_MASK | X86_TF_MASK);
 X86_CS = (read_b((num << 2) + 3) << 8) + read_b((num << 2) + 2);
 X86_IP = (read_b((num << 2) + 1) << 8) + read_b((num << 2));

 /* fprintf(stderr, "Leaving interrupt call.\n"); */
}

thus, the handler is getting called at every iteration in the main emulation processor loop (decode.c ) since having been initially raised. Loop turns into indefinite one. Verified today.

void X86EMU_exec(void)
{
 u8 op1;

 M.x86.intr = 0;
 DB(x86emu_end_instr();)

    for (;;) {
DB( if (CHECK_IP_FETCH())
    x86emu_check_ip_access();)
  /* If debugging, save the IP and CS values. */
  SAVE_IP_CS(M.x86.R_CS, M.x86.R_IP);
  INC_DECODED_INST_LEN(1);
  if (M.x86.intr) {
   if (M.x86.intr & INTR_HALTED) { // ENTERED EVERY TIME after interrupt is raised - DK !!!
DB(
    X86EMU_trace_regs();)
    return;
            }
   if (((M.x86.intr & INTR_SYNCH) && (M.x86.intno == 0 || M.x86.intno == 2)) ||
    !ACCESS_FLAG(F_IF)) {
    x86emu_intr_handle();
   }
  }
  if ((M.x86.R_CS == 0) && (M.x86.R_IP == 0)) {
DB(
                                X86EMU_trace_regs();)
                                return;
  }

  op1 = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
  // fprintf (stderr, "%s", M.x86.decoded_buf);
  // x86emu_dump_regs();
  (*x86emu_optab[op1])(op1);
    }
}

Package - Libx86_1.1, x86 Emulation part.
UBUNTU 10.04 LTS

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.