x86: Fixes TLS bug causing kernel page faults
[akaros.git] / kern / arch / sparc / timer.c
1 #include <arch/timer.h>
2 #include <ros/common.h>
3 #include <arch/trap.h>
4 #include <arch/arch.h>
5 #include <stdio.h>
6 #include <assert.h>
7
8 #ifdef __SHARC__
9 #pragma nosharc
10 #endif
11
12 system_timing_t system_timing = {0};
13 volatile uint32_t timer_ticks = 0;
14
15 asm (
16 ".global handle_timer_interrupt         \n\t"
17 "handle_timer_interrupt:                \n\t"
18 "       mov     " XSTR(CORE_ID_REG) ",%l3       \n\t"
19 "       mov     %psr,%l4                        \n\t"
20 "       cmp     %l3,0                           \n\t"
21 "       bne     1f                              \n\t"
22 "        mov    %l4,%psr                        \n\t"
23 "       sethi   %hi(timer_ticks),%l4            \n\t"
24 "       ld      [%l4+%lo(timer_ticks)],%l5      \n\t"
25 "       inc     %l5                             \n\t"
26 "       st      %l5,[%l4+%lo(timer_ticks)]      \n\t"
27 "1:     jmp     %l1                             \n\t"
28 "        rett   %l2                             \n\t" );
29
30 void
31 timer_init(void)
32 {       
33         system_timing.tsc_freq = TSC_HZ;
34         cprintf("TSC Frequency: %llu\n", system_timing.tsc_freq);
35 }
36
37 void
38 set_timer(uint32_t usec)
39 {
40         uint32_t clocks =  (uint64_t)usec*TSC_HZ/1000000;
41         if(clocks & (clocks-1))
42         {
43                 clocks = ROUNDUPPWR2(clocks);
44                 warn("set_timer: rounding up to %d usec",
45                      (uint64_t)clocks*1000000/TSC_HZ);
46         }
47         if(clocks > TIMER_MAX_PERIOD)
48         {
49                 clocks = TIMER_MAX_PERIOD;
50                 warn("set_timer: truncating to %d usec",
51                      (uint64_t)clocks*1000000/TSC_HZ);
52         }
53         sparc_set_timer(clocks,!!clocks);
54 }
55
56 void
57 udelay(uint64_t usec)
58 {
59         if (system_timing.tsc_freq != 0)
60         {
61                 uint64_t start, end, now;
62         
63                 start = read_tsc();
64                 end = start + (system_timing.tsc_freq * usec) / 1000000;
65
66                 do
67                 {
68                         cpu_relax();
69                         now = read_tsc();
70                 } while (now < end || (now > start && end < start));
71         }
72         else panic("udelay() was called before timer_init(), moron!");
73 }