Merge branch 'master' of ssh://waterman@scm.millennium.berkeley.edu/project/cs/radlab...
authorAndrew Waterman <waterman@parcad.millennium.berkeley.edu>
Tue, 19 Jan 2010 23:23:01 +0000 (15:23 -0800)
committerAndrew Waterman <waterman@parcad.millennium.berkeley.edu>
Tue, 19 Jan 2010 23:23:01 +0000 (15:23 -0800)
kern/arch/i386/apic.c
kern/arch/sparc/sparc.h
kern/arch/sparc/timer.c
kern/arch/sparc/timer.h
kern/arch/sparc/trap_entry.S
kern/include/timing.h

index 0b45c54..92c4ee1 100644 (file)
@@ -90,6 +90,11 @@ void lapic_set_timer(uint32_t usec, bool periodic)
                          LAPIC_TIMER_DEFAULT_DIVISOR);
 }
 
+void set_timer(uint32_t usec)
+{
+       lapic_set_timer(usec,!!usec);
+}
+
 uint32_t lapic_get_default_id(void)
 {
        uint32_t ebx;
index 192ac4c..eeb10c4 100644 (file)
@@ -165,13 +165,27 @@ mmu_probe(uint32_t va)
        return load_alternate((va & ~0xFFF) | 0x400, 3);
 }
 
+static __inline void
+store_iobus(uint32_t device, uint32_t addr, uint32_t data)
+{
+       store_alternate(device << 16 | addr, 2, data);
+}
+
 static __inline uint32_t
 send_ipi(uint32_t dst)
 {
-       store_alternate(2 << 16 | dst << 10, 2, 0);
+       store_iobus(2,dst<<10,0);
        return 0;
 }
 
+// arm the calling core's interrupt timer.
+// enable must be 1 or 0; clocks must be a power of 2
+static __inline void
+sparc_set_timer(uint32_t clocks, uint32_t enable)
+{
+       store_iobus(1,0,enable << 24 | (clocks-1));
+}
+
 #endif /* !__ASSEMBLER__ */
 
 #endif /* !ROS_INC_X86_H */
index 01ceef2..820333a 100644 (file)
@@ -30,25 +30,30 @@ asm (
 void
 timer_init(void)
 {      
-#if 0
-       uint32_t ticks = timer_ticks;
-       uint64_t tsc_ticks;
-
-       while(ticks == timer_ticks) ;
-
-       ticks = timer_ticks;
-       tsc_ticks = read_tsc();
-
-       while(ticks == timer_ticks) ;
-
-       system_timing.tsc_freq = (read_tsc() - tsc_ticks)*INTERRUPT_TIMER_HZ;
-#endif
-       system_timing.tsc_freq = 1000000;
-
+       system_timing.tsc_freq = TSC_HZ;
        cprintf("TSC Frequency: %llu\n", system_timing.tsc_freq);
 }
 
 void
+set_timer(uint32_t usec)
+{
+       uint32_t clocks =  (uint64_t)usec*TSC_HZ/1000000;
+       if(clocks & (clocks-1))
+       {
+               clocks = ROUNDUPPWR2(clocks);
+               warn("set_timer: rounding up to %d usec",
+                    (uint64_t)clocks*1000000/TSC_HZ);
+       }
+       if(clocks > TIMER_MAX_PERIOD)
+       {
+               clocks = TIMER_MAX_PERIOD;
+               warn("set_timer: truncating to %d usec",
+                    (uint64_t)clocks*1000000/TSC_HZ);
+       }
+       sparc_set_timer(clocks,!!clocks);
+}
+
+void
 udelay(uint64_t usec)
 {
        if (system_timing.tsc_freq != 0)
index 37264b4..7d0e030 100644 (file)
@@ -1,7 +1,8 @@
 #ifndef ROS_ARCH_TIMER_H
 #define ROS_ARCH_TIMER_H
 
-#define INTERRUPT_TIMER_HZ     100
+#define TSC_HZ 1000000 // really, this is the core clock frequency
+#define TIMER_MAX_PERIOD (1 << 24) // in cycles
 
 #include <ros/common.h>
 
index afb6bcf..e244e5b 100644 (file)
@@ -141,10 +141,31 @@ env_save_tf:
        .global env_pop_tf
 env_pop_tf:
 
-       // disable interrupts.
+       mov     %psr,%o1
+       btst    PSR_PS,%o1      ! return to kernel or user?
+       bne     1f
+
+       // we're returning to userspace.
+       wr      %o1,PSR_ET,%psr
+
+       // CWP = 0 (therefore 1 after rett), so set window 2 invalid
+       mov     0,%wim
+       mov     %o0,%g2
+       mov     %psr,%g1
+       andn    %g1,PSR_CWP,%g1
+       mov     %g1,%psr
+       mov     1<<2,%wim; nop
+       // time to restore user context and rett
+       ba      4f
+        mov    %g2,%o0
+
+1:
+       // this general version of the code works for kernel and user,
+       // but it is slow because it spills the windows.
+
+       // first disable interrupts.
        // since wrpsr/rdpsr is interruptible, all interrupt handlers
        // must restore the psr to its interrupt-time value
-       mov     %psr,%o1
        or      %o1,PSR_PIL,%o2
        wr      %o2,%psr
 
@@ -162,7 +183,6 @@ env_pop_tf:
        bne,a   6b
         restore
        
-
        // disable traps, and restore interrupt level
        wr      %o2,PSR_ET,%psr
        wr      %o1,PSR_ET,%psr
@@ -171,33 +191,9 @@ env_pop_tf:
        // then (CWP+1) % NWINDOWS should be invalid.  fix that.
        save
        mov     %i0,%o0
+       mov     %o0,%g2
 
-#if 0
-       // is (CWP+1) % NWINDOWS valid?
-       and     %o1,PSR_CWP,%o2
-       set     NWINDOWS,%o1
-       ld      [%o1],%o1
-       add     %o2,1,%o2
-       cmp     %o2,%o1
-       be,a    3f
-        mov    0,%o2
-
-3:     mov     1,%o3
-       sll     %o3,%o2,%o2             ! %o2 = 1 << ((CWP+1)%NWINDOWS)
-       mov     %wim,%o3
-       btst    %o2,%o3                 ! (%wim & %o2) == 0?
-       be      4f
-        nop
-
-       sethi   %hi(fill),%o3           ! gotta fill a window
-       jmpl    %lo(fill)+%o3,%o3
-        save   %o3,0,%l7               ! fill returns to %l7
-       restore
-
-#endif
-
-       // restore user context
-4:     mov     %o0,%g2
+4:     // restore user context
        restore
        ldd     [%g2+32],%o0
        ldd     [%g2+40],%o2
@@ -224,10 +220,8 @@ env_pop_tf:
        andn    %l0,PSR_CWP,%l0
        wr      %l2,%l0,%psr
 
-       ldd     [%o0+136],%l2
-       !mov    %l3,%wim
-       ldd     [%o0+144],%l4
-       mov     %l4,%tbr
+       ld      [%o0+136],%l2
+       ld      [%o0+148],%l5
        mov     %l5,%y
        nop
 
@@ -242,8 +236,3 @@ handle_perfctr:
        lda     [%i1] 2,%i1
        jmp     %l2
         rett   %l2+4
-
-       .global send_active_message_raw
-send_active_message_raw:
-       retl
-        .word  0x81f00000
index 0edd068..5ee9f08 100644 (file)
@@ -5,4 +5,8 @@
 
 void udelay(uint64_t usec);
 
+// arm the programmable interrupt timer.
+// usec=0 disables it.
+void set_timer(uint32_t usec);
+
 #endif