POP_FRAME
iret
+ .text
+ SUPERALIGN_TEXT
+ .globl Xtimer
+Xtimer:
+ PUSH_FRAME
+ movl $0, lapic_eoi /* End Of Interrupt to APIC */
+ FAKE_MCOUNT(15*4(%esp))
+
+ movl PCPU(curthread),%ebx
+ cmpl $TDPRI_CRIT,TD_PRI(%ebx)
+ jge 1f
+ subl $8,%esp /* make same as interrupt frame */
+ pushl %esp /* pass frame by reference */
+ incl PCPU(intr_nesting_level)
+ addl $TDPRI_CRIT,TD_PRI(%ebx)
+ call lapic_timer_process_frame
+ subl $TDPRI_CRIT,TD_PRI(%ebx)
+ decl PCPU(intr_nesting_level)
+ addl $12,%esp
+ pushl $0 /* CPL for frame (REMOVED) */
+ MEXITCOUNT
+ jmp doreti
+1:
+ orl $RQF_TIMER,PCPU(reqflags)
+ MEXITCOUNT
+ POP_FRAME
+ iret
+
#ifdef APIC_IO
MCOUNT_LABEL(bintr)
static void lapic_timer_calibrate(void);
static void lapic_timer_set_divisor(int);
+void lapic_timer_process(void);
+void lapic_timer_process_frame(struct intrframe *);
/*
* pointers to pmapped apic hardware.
void
apic_initialize(boolean_t bsp)
{
+ uint32_t timer;
u_int temp;
/*
/*
* Mask the apic error interrupt, apic performance counter
- * interrupt, and the apic timer interrupt.
+ * interrupt.
*/
lapic.lvt_error = lapic.lvt_error | APIC_LVT_MASKED;
lapic.lvt_pcint = lapic.lvt_pcint | APIC_LVT_MASKED;
- lapic.lvt_timer = lapic.lvt_timer | APIC_LVT_MASKED;
+
+ /* Set apic timer vector and mask the apic timer interrupt. */
+ timer = lapic.lvt_timer;
+ timer &= ~APIC_LVTT_VECTOR;
+ timer |= XTIMER_OFFSET;
+ timer |= APIC_LVTT_MASKED;
+ lapic.lvt_timer = timer;
/*
* Set the Task Priority Register as needed. At the moment allow
lapic_timer_divisor_idx, lapic_timer_freq);
}
+void
+lapic_timer_process(void)
+{
+}
+
+void
+lapic_timer_process_frame(struct intrframe *frame)
+{
+}
+
/*
* dump contents of local APIC registers
ASSYM(RQF_AST_USER_RESCHED, RQF_AST_USER_RESCHED);
ASSYM(RQF_AST_LWKT_RESCHED, RQF_AST_LWKT_RESCHED);
ASSYM(RQF_AST_UPCALL, RQF_AST_UPCALL);
+ASSYM(RQF_TIMER, RQF_TIMER);
ASSYM(RQF_AST_MASK, RQF_AST_MASK);
ASSYM(FIRST_SOFTINT, FIRST_SOFTINT);
/* install an inter-CPU IPI for IPIQ messaging */
setidt(XIPIQ_OFFSET, Xipiq,
SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
+
+ /* install a timer vector */
+ setidt(XTIMER_OFFSET, Xtimer,
+ SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
/* install an inter-CPU IPI for CPU stop/restart */
setidt(XCPUSTOP_OFFSET, Xcpustop,
/* IPIQ rendezvous */
#define XIPIQ_OFFSET (IDT_OFFSET + 115)
+/* TIMER rendezvous */
+#define XTIMER_OFFSET (IDT_OFFSET + 116)
+
/* IPI to signal CPUs to stop and wait for another CPU to restart them */
#define XCPUSTOP_OFFSET (IDT_OFFSET + 128)
Xforward_irq, /* Forward irq to cpu holding ISR lock */
Xcpustop, /* CPU stops & waits for another CPU to restart it */
Xspuriousint, /* handle APIC "spurious INTs" */
+ Xtimer, /* handle LAPIC timer INT */
Xipiq; /* handle lwkt_send_ipiq() requests */
#endif /* SMP */
#ifdef SMP
testl $RQF_IPIQ,PCPU(reqflags)
jnz doreti_ipiq
+ testl $RQF_TIMER,PCPU(reqflags)
+ jnz doreti_timer
#endif
testl PCPU(fpending),%ecx /* check for an unmasked fast int */
jnz doreti_fast
movl %esi,%eax /* restore cpl for loop */
jmp doreti_next
+doreti_timer:
+ movl %eax,%esi /* save cpl (can't use stack) */
+ incl PCPU(intr_nesting_level)
+ andl $~RQF_TIMER,PCPU(reqflags)
+ subl $8,%esp /* add dummy vec and ppl */
+ pushl %esp /* pass frame by reference */
+ call lapic_timer_process_frame
+ addl $12,%esp
+ decl PCPU(intr_nesting_level)
+ movl %esi,%eax /* restore cpl for loop */
+ jmp doreti_next
+
#endif
/*
#ifdef SMP
testl $RQF_IPIQ,PCPU(reqflags)
jnz splz_ipiq
+ testl $RQF_TIMER,PCPU(reqflags)
+ jnz splz_timer
#endif
testl PCPU(fpending),%ecx /* check for an unmasked fast int */
jnz splz_fast
call lwkt_process_ipiq
popl %eax
jmp splz_next
+
+splz_timer:
+ andl $~RQF_TIMER,PCPU(reqflags)
+ pushl %eax
+ call lapic_timer_process
+ popl %eax
+ jmp splz_next
#endif
/*
#define RQB_AST_USER_RESCHED 4
#define RQB_AST_LWKT_RESCHED 5
#define RQB_AST_UPCALL 6
+#define RQB_TIMER 7
#define RQF_IPIQ (1 << RQB_IPIQ)
#define RQF_INTPEND (1 << RQB_INTPEND)
+#define RQF_TIMER (1 << RQB_TIMER)
#define RQF_AST_OWEUPC (1 << RQB_AST_OWEUPC)
#define RQF_AST_SIGNAL (1 << RQB_AST_SIGNAL)
#define RQF_AST_USER_RESCHED (1 << RQB_AST_USER_RESCHED)
#define RQF_AST_MASK (RQF_AST_OWEUPC|RQF_AST_SIGNAL|\
RQF_AST_USER_RESCHED|RQF_AST_LWKT_RESCHED|\
RQF_AST_UPCALL)
-#define RQF_IDLECHECK_MASK (RQF_IPIQ|RQF_INTPEND)
+#define RQF_IDLECHECK_MASK (RQF_IPIQ|RQF_INTPEND|RQF_TIMER)
#endif