next up previous contents
Next: 4.1.9.1 Interrupt delivering Up: 4.1 Input/Output Previous: 4.1.8 Traps and interrupts

4.1.9 Events for ix86 based architectures

\subsubsection{Interrupt tables and interrupt masks}

On Intels we tolerate up to 32 interrupts and up to 255 traps4.6. We must include also some space for virtual traps and virtual interrupts.

<Off machine dependent interrupt table size. >= (U->)
const natural_t OFF_MDEP_NPINT_MAX=32; // 32 actual interrupts on intels.
const natural_t OFF_MDEP_NINT_MAX=OFF_MDEP_NPINT_MAX+OFF_MDEP_NVINT_MAX;
Defines OFF_MDEP_NINT_MAX, OFF_MDEP_NPINT_MAX (links are to index).

<Off machine dependent trap table size. >= (U->)
const natural_t OFF_MDEP_NPTRP_MAX=0x100; // 256 trap entries on intels. 
const natural_t OFF_MDEP_NTRP_MAX=OFF_MDEP_NPTRP_MAX+OFF_MDEP_NVTRP_MAX;
Defines OFF_MDEP_NPTRP_MAX, OFF_MDEP_NTRP_MAX (links are to index).

The maximum number of virtual trap and virtual interrupts are system limits.

<Off limits. >+= [<-D]
const int OFF_MDEP_NVINT_MAX=8; // 8 virtual timers.
const int OFF_MDEP_NVTRP_MAX=9; // 9 virtual traps
Defines OFF_MDEP_NVINT_MAX, OFF_MDEP_NVTRP_MAX (links are to index).

<Off machine dependent event table dependencies. >= (U->) [D->]
#include <klib/limits.h>        // for OFF_MDEP_NV{INT,TRP}_MAX
#include <flux/types.h>         // for boolean_t natural_t et al.

Another constant is defined to identify the first virtual interrupt.

<Off machine dependent interrupt numbers. >= (U->) [D->]
// Irq # for the first virtual interrupt line.
const natural_t OFF_MDEP_VINT0_IRQ=OFF_MDEP_NPINT_MAX;

We maintain a machine dependent interrupt table per interrupt table. It deals with interrupt masks and also with IDT handling.

<Off machine dependent interrupt table. >= (U->)
// An ix86 interrupt table
//
class off_mdepIntTbl {
public:
  // Creates an x86 interrupt table. 
  off_mdepIntTbl(void);

  // Masks the interrupt.
  void mask(natural_t i);
  // Unmasks the interrupt.
  void unmask(natural_t i);
  // Is it masked?.
  inline boolean_t is_masked(natural_t i) const;

private:
  <Other private members of off_mdepIntTbl. >
};

Defines off_mdepIntTbl (links are to index).

An interrupt mask is an integer with one bit set per enabled interrupt. Only real interrupts can be masked; virtual interrupts are non maskable.

<Off machine dependent interrupt mask. >= (U->)
class off_mdepIrqMask {
private: 
  natural_t i_mask;              // Interrupt mask
public:
  off_mdepIrqMask(natural_t val=0) : i_mask(val) {;}
  void mask(natural_t i)     { 
    if (i < OFF_MDEP_NPINT_MAX)
      set_bit(i,(void*)&i_mask); 
  }
  void unmask(natural_t i )  { 
    if (i < OFF_MDEP_NPINT_MAX)
      clear_bit(i,(void*)&i_mask); 
  }
  boolean_t is_masked(natural_t i) const {
    if (i < OFF_MDEP_NPINT_MAX)
      return test_bit(i,(void*)&i_mask); 
    else
      return FALSE;
  }
  boolean_t is_empty(void)         const { return i_mask==0; }
};

Defines off_mdepIrqMask (links are to index).

<Off machine dependent event table dependencies. >+= (U->) [<-D->]
#include <flux/machine/bitops.h> // for set_,clear_ and test_bit

Such mask is stored in i_mask.

<Other private members of off_mdepIntTbl. >= (<-U)
off_mdepIrqMask i_mask; 

It is initialized at instantiation time with every interrupt cleared.

<off_mdepIntTbl::off_mdepIntTbl implementation. >= (U->)
// Creates an x86 interrupt table. 
off_mdepIntTbl::off_mdepIntTbl(void) : 
  i_mask(0) 
{
  <Machine dependent interrupt hardware initialization. >
}

After that, mask and unmask requests are handled by programming the PIC and setting the bit in the i_mask.

<off_mdepIntTbl::is_masked implementation. >= (U->)
// Is it masked?.
inline boolean_t off_mdepIntTbl::is_masked(natural_t i) const
{
  assert(i<OFF_MDEP_NINT_MAX);
  return i_mask.is_masked(i);
}

<Off machine dependent event table dependencies. >+= (U->) [<-D->]
#include <assert.h>              // for assert

<off_mdepIntTbl::mask implementation. >= (U->)
// Masks the interrupt.
void off_mdepIntTbl::mask(natural_t i)
{
  assert(i<OFF_MDEP_NINT_MAX);
  if (is_masked(i))
    return;
  i_mask.mask(i);
  pic_disable_irq(i);
}

The real work is done by pic_disable_irq.

<Off machine dependent event table implementation dependencies. >= (U->) [D->]
#include <flux/machine/pc/pic.h> //  for pic_disable_irq et al.

<off_mdepIntTbl::unmask implementation. >= (U->)
// Unmasks the interrupt.
void off_mdepIntTbl::unmask(natural_t i)
{
  assert( i<OFF_MDEP_NINT_MAX);
  if (!is_masked(i))
    return;
  i_mask.unmask(i);
  pic_enable_irq(i);

}



 

Francisco J. Ballesteros
1998-05-25