lapic timer: Add necessary bits for lapic timer interrupt delivery
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Sat, 2 May 2009 05:50:34 +0000 (13:50 +0800)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Sat, 2 May 2009 13:53:47 +0000 (21:53 +0800)
The implementation in ipl.s and apic_vector.s is based on our ipiq
processing.

sys/platform/pc32/apic/apic_vector.s
sys/platform/pc32/apic/mpapic.c
sys/platform/pc32/i386/genassym.c
sys/platform/pc32/i386/mp_machdep.c
sys/platform/pc32/isa/intr_machdep.h
sys/platform/pc32/isa/ipl.s
sys/sys/globaldata.h

index 584de57..a208f78 100644 (file)
@@ -403,6 +403,34 @@ Xipiq:
        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)
index b60f497..4fef209 100644 (file)
@@ -43,6 +43,8 @@
 
 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.
@@ -66,6 +68,7 @@ static const uint32_t lapic_timer_divisors[] = {
 void
 apic_initialize(boolean_t bsp)
 {
+       uint32_t timer;
        u_int   temp;
 
        /*
@@ -99,11 +102,17 @@ apic_initialize(boolean_t bsp)
 
        /*
         * 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
@@ -224,6 +233,16 @@ lapic_timer_calibrate(void)
                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
index 8170d0a..f6ec7df 100644 (file)
@@ -193,6 +193,7 @@ ASSYM(RQF_AST_SIGNAL, RQF_AST_SIGNAL);
 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);
index 023eedb..fc16a60 100644 (file)
@@ -561,6 +561,10 @@ mp_enable(u_int boot_addr)
        /* 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,
index 93ed679..121b210 100644 (file)
 /* 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)
 
@@ -147,6 +150,7 @@ inthand_t
        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 */
 
index 172a819..3593ec3 100644 (file)
@@ -125,6 +125,8 @@ doreti_next:
 #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
@@ -334,6 +336,18 @@ doreti_ipiq:
        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
 
        /*
@@ -360,6 +374,8 @@ splz_next:
 #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
@@ -477,6 +493,13 @@ splz_ipiq:
        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
 
        /*
index 9e46088..c0cdef3 100644 (file)
@@ -179,9 +179,11 @@ typedef struct globaldata *globaldata_t;
 #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)
@@ -190,7 +192,7 @@ typedef struct globaldata *globaldata_t;
 #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