- Add a function to set the Task Priority Register (TPR) of the local APIC.

Currently this is only used to initiailize the TPR to 0 during initial
  setup.
- Reallocate vectors for the local APIC timer, error, and thermal LVT
  entries.  The timer entry is allocated from the top of the I/O interrupt
  range reducing the number of vectors available for hardware interrupts
  to 191.  Linux happens to use the same exact vector for its timer
  interrupt as well.  If the timer vector shared the same priority queue
  as the IPI handlers, then the frequency that the timer vector will
  eventually be firing at can interact badly with the IPIs resulting in
  the queue filling and the dreaded IPI stuck panics, hence it being located
  at the top of the previous priority queue instead.
- Fixup various minor nits in comments.
This commit is contained in:
John Baldwin 2004-12-23 19:47:59 +00:00
parent 880904c323
commit dfa7bc486b
2 changed files with 39 additions and 18 deletions

View File

@ -60,7 +60,9 @@ __FBSDID("$FreeBSD$");
#define MAX_APICID 16
/* Sanity checks on IDT vectors. */
CTASSERT(APIC_IO_INTS + APIC_NUM_IOINTS <= APIC_LOCAL_INTS);
CTASSERT(APIC_IO_INTS + APIC_NUM_IOINTS == APIC_TIMER_INT);
CTASSERT(APIC_TIMER_INT < APIC_LOCAL_INTS);
CTASSERT(APIC_LOCAL_INTS == 240);
CTASSERT(IPI_STOP < APIC_SPURIOUS_INT);
/*
@ -264,10 +266,8 @@ lapic_setup(void)
/* XXX: more LVT entries */
/* Clear the TPR. */
value = lapic->tpr;
value &= ~APIC_TPR_PRIO;
lapic->tpr = value;
/* Initialize the TPR to allow all interrupts. */
lapic_set_tpr(0);
/* Use the cluster model for logical IDs. */
value = lapic->dfr;
@ -472,6 +472,24 @@ lapic_set_lvt_triggermode(u_int apic_id, u_int pin, enum intr_trigger trigger)
return (0);
}
/*
* Adjust the TPR of the current CPU so that it blocks all interrupts below
* the passed in vector.
*/
void
lapic_set_tpr(u_int vector)
{
#ifdef CHEAP_TPR
lapic->tpr = vector;
#else
u_int32_t tpr;
tpr = lapic->tpr & ~APIC_TPR_PRIO;
tpr |= vector;
lapic->tpr = tpr;
#endif
}
void
lapic_eoi(void)
{
@ -637,10 +655,9 @@ SYSINIT(apic_setup_io, SI_SUB_INTR, SI_ORDER_SECOND, apic_setup_io, NULL)
#ifdef SMP
/*
* Inter Processor Interrupt functions. The lapic_ipi_*() functions are
* private the sys/i386 code. The public interface for the rest of the
* private to the sys/i386 code. The public interface for the rest of the
* kernel is defined in mp_machdep.c.
*/
int
lapic_ipi_wait(int delay)
{
@ -745,7 +762,7 @@ lapic_ipi_vectored(u_int vector, int dest)
* the failure with the check above when the next IPI is
* sent.
*
* We could skiip this wait entirely, EXCEPT it probably
* We could skip this wait entirely, EXCEPT it probably
* protects us from other routines that assume that the
* message was delivered and acted upon when this function
* returns.

View File

@ -42,7 +42,7 @@
* 0xff (255) +-------------+
* | | 15 (Spurious / IPIs / Local Interrupts)
* 0xf0 (240) +-------------+
* | | 14 (I/O Interrupts)
* | | 14 (I/O Interrupts / Timer)
* 0xe0 (224) +-------------+
* | | 13 (I/O Interrupts)
* 0xd0 (208) +-------------+
@ -78,8 +78,13 @@
*/
#define APIC_ID_ALL 0xff
/* I/O Interrupts are used for external devices such as ISA, PCI, etc. */
#define APIC_IO_INTS (IDT_IO_INTS + 16)
#define APIC_NUM_IOINTS 192
#define APIC_NUM_IOINTS 191
/* The timer interrupt is used for clock handling and drives hardclock, etc. */
#define APIC_TIMER_INT (APIC_IO_INTS + APIC_NUM_IOINTS)
/*
********************* !!! WARNING !!! ******************************
@ -101,15 +106,12 @@
* other deadlocks caused by IPI_STOP.
*/
/* Interrupts for local APIC LVT entries other than the timer. */
#define APIC_LOCAL_INTS 240
#define APIC_ERROR_INT APIC_LOCAL_INTS
#define APIC_THERMAL_INT (APIC_LOCAL_INTS + 1)
#if 0
#define APIC_TIMER_INT (APIC_LOCAL_INTS + X)
#define APIC_ERROR_INT (APIC_LOCAL_INTS + X)
#define APIC_THERMAL_INT (APIC_LOCAL_INTS + X)
#endif
#define APIC_IPI_INTS (APIC_LOCAL_INTS + 0)
#define APIC_IPI_INTS (APIC_LOCAL_INTS + 2)
#define IPI_RENDEZVOUS (APIC_IPI_INTS) /* Inter-CPU rendezvous. */
#define IPI_INVLTLB (APIC_IPI_INTS + 1) /* TLB Shootdown IPIs */
#define IPI_INVLPG (APIC_IPI_INTS + 2)
@ -127,7 +129,8 @@
#define IPI_STOP (APIC_IPI_INTS + 6) /* Stop CPU until restarted. */
/* The spurious interrupt can share the priority class with the IPIs since
/*
* The spurious interrupt can share the priority class with the IPIs since
* it is not a normal interrupt. (Does not use the APIC's interrupt fifo)
*/
#define APIC_SPURIOUS_INT 255
@ -206,6 +209,7 @@ int lapic_set_lvt_polarity(u_int apic_id, u_int lvt,
enum intr_polarity pol);
int lapic_set_lvt_triggermode(u_int apic_id, u_int lvt,
enum intr_trigger trigger);
void lapic_set_tpr(u_int vector);
void lapic_setup(void);
#endif /* !LOCORE */