Merge branch 'master' of ssh://scm.millennium.berkeley.edu/project/cs/radlab/src...
[akaros.git] / kern / arch / sparc / arch.h
1 #ifndef ROS_INC_ARCH_H
2 #define ROS_INC_ARCH_H
3
4 /* Arch Constants */
5 #define MAX_NUM_CPUS            64
6 #define IOAPIC_BASE             0xFEC00000 // max virtual address
7
8 #include <arch/mmu.h>
9 #include <arch/sparc.h>
10
11 #ifndef __ASSEMBLER__
12
13 #include <ros/common.h>
14 #include <arch/timer.h>
15
16 static __inline void breakpoint(void) __attribute__((always_inline));
17 static __inline void invlpg(void *addr) __attribute__((always_inline));
18 static __inline uint64_t read_tsc(void) __attribute__((always_inline));
19 static __inline uint64_t read_tsc_serialized(void) __attribute__((always_inline));
20 static __inline void enable_irq(void) __attribute__((always_inline));
21 static __inline void disable_irq(void) __attribute__((always_inline));
22 static __inline void enable_irqsave(int8_t* state) __attribute__((always_inline));
23 static __inline void disable_irqsave(int8_t* state) __attribute__((always_inline));
24 static __inline void cpu_relax(void) __attribute__((always_inline));
25 static __inline void cpu_halt(void) __attribute__((always_inline));
26 static __inline void clflush(uintptr_t* addr) __attribute__((always_inline));
27 static __inline int irq_is_enabled(void) __attribute__((always_inline));
28 static __inline uint32_t core_id(void) __attribute__((always_inline));
29 static __inline void cache_flush(void) __attribute__((always_inline));
30 static __inline void reboot(void) __attribute__((always_inline)) __attribute__((noreturn));
31 static __inline void lcr3(uint32_t val) __attribute__((always_inline));
32 static __inline uint32_t rcr3(void) __attribute__((always_inline));
33
34 void print_cpuinfo(void);
35 void show_mapping(uintptr_t start, size_t size);
36 void backtrace(void);
37
38 static __inline void
39 breakpoint(void)
40 {
41         __asm __volatile("ta 0x7f");
42 }
43
44 static __inline void 
45 invlpg(void *addr)
46
47         store_alternate(((intptr_t)addr) & ~0xFFF,3,0);
48 }  
49
50 static __inline void
51 tlbflush(void)
52 {
53         // unsure if we'll support this yet...
54         // may have to just do invlpg() in a loop
55         store_alternate(0x400,3,0);
56 }
57
58 static __inline uint64_t
59 read_tsc(void)
60 {
61         return read_perfctr(0);
62 }
63
64 static __inline uint64_t 
65 read_tsc_serialized(void)
66 {
67         return read_tsc();
68 }
69
70 static __inline void
71 enable_irq(void)
72 {
73         write_psr(read_psr() & ~0xF00);
74 }
75
76 static __inline void
77 disable_irq(void)
78 {
79         write_psr(read_psr() | 0xF00);
80 }
81
82 static __inline void
83 enable_irqsave(int8_t* state)
84 {
85         // *state tracks the number of nested enables and disables
86         // initial value of state: 0 = first run / no favorite
87         // > 0 means more enabled calls have been made
88         // < 0 means more disabled calls have been made
89         // Mostly doing this so we can call disable_irqsave first if we want
90
91         // one side or another "gets a point" if interrupts were already the
92         // way it wanted to go.  o/w, state stays at 0.  if the state was not 0
93         // then, enabling/disabling isn't even an option.  just increment/decrement
94
95         // if enabling is winning or tied, make sure it's enabled
96         if ((*state == 0) && !irq_is_enabled())
97                 enable_irq();
98         else
99                 (*state)++;
100 }
101
102 static __inline void
103 disable_irqsave(int8_t* state)
104 {
105         if ((*state == 0) && irq_is_enabled())
106                 disable_irq();
107         else 
108                 (*state)--;
109 }
110
111 static __inline void
112 cpu_relax(void)
113 {
114         int ctr = 8;
115         asm volatile("1: deccc %0; bne 1b; nop" :
116                      "=r"(ctr) : "0"(ctr) : "cc","memory");
117 }
118
119 static __inline void
120 cpu_halt(void)
121 {
122         asm volatile("1: ba 1b; nop" : : : "memory");
123 }
124
125 static __inline void
126 clflush(uintptr_t* addr)
127 {
128         asm volatile("flush %0" : : "r"(addr));
129 }
130
131 static __inline int
132 irq_is_enabled(void)
133 {
134         return (read_psr() & 0xF00) == 0;
135 }
136
137 static __inline uint32_t
138 core_id(void)
139 {
140         uint32_t reg;
141         __asm__ __volatile__("mov %" XSTR(CORE_ID_REG) ",%0" : "=r"(reg));
142         return reg;
143 }
144
145 static __inline void
146 cache_flush(void)
147 {
148 }
149
150 static __inline void
151 reboot(void)
152 {
153         while(1);
154 }
155
156 static __inline void
157 lcr3(uint32_t val)
158 {
159         extern uintptr_t mmu_context_table[NCONTEXTS];
160         *mmu_context_table = val >> 4 | PTE_PTD;
161         tlbflush();
162 }
163
164 static __inline uint32_t
165 rcr3(void)
166 {
167         extern uintptr_t mmu_context_table[NCONTEXTS];
168         return (*mmu_context_table & ~0x3) << 4;
169 }
170
171 #endif /* !__ASSEMBLER__ */
172
173 #endif /* !ROS_INC_X86_H */