Exposed per-core timer interrupts on SPARC
[akaros.git] / kern / arch / sparc / sparc.h
1 #ifndef ROS_INC_SPARC_H
2 #define ROS_INC_SPARC_H
3
4 #define CORE_ID_REG     %asr15
5 #define NUM_CORES_REG   %asr14
6 #define MEMSIZE_MB_REG  %asr13
7
8 #define PSR_CWP         0x0000001F
9 #define PSR_ET          0x00000020
10 #define PSR_PS          0x00000040
11 #define PSR_S           0x00000080
12 #define PSR_PIL         0x00000F00
13 #define PSR_EF          0x00001000
14 #define PSR_EC          0x00002000
15 #define PSR_RESERVED    0x000FC000
16 #define PSR_ICC         0x00F00000
17 #define PSR_VER         0x0F000000
18 #define PSR_IMPL        0xF0000000
19
20 #ifndef __ASSEMBLER__
21
22 #define STR(arg) #arg
23 #define XSTR(arg) STR(arg)
24
25 #include <ros/common.h>
26 #include <arch/timer.h>
27
28 static __inline uint32_t read_psr(void) __attribute__((always_inline));
29 static __inline uint32_t read_wim(void) __attribute__((always_inline));
30 static __inline uint32_t read_tbr(void) __attribute__((always_inline));
31 static __inline uint32_t read_mmu_reg(uint32_t which) __attribute__((always_inline));
32 static __inline uint32_t read_y(void) __attribute__((always_inline));
33 static __inline uint32_t read_fsr(void) __attribute__((always_inline));
34 static __inline uint64_t read_perfctr(uint32_t core, uint32_t which) __attribute__((always_inline));
35 static __inline void write_psr(uint32_t val) __attribute__((always_inline));
36 static __inline void write_wim(uint32_t val) __attribute__((always_inline));
37 static __inline void write_tbr(uint32_t val) __attribute__((always_inline));
38 static __inline void write_mmu_reg(uint32_t which, uint32_t val) __attribute__((always_inline));
39 static __inline void write_y(uint32_t val) __attribute__((always_inline));
40 static __inline void write_fsr(uint32_t val) __attribute__((always_inline));
41 static __inline uint32_t memsize_mb(void) __attribute__((always_inline));
42 static __inline uint32_t mmu_probe(uint32_t va) __attribute__((always_inline));
43 static __inline uint32_t send_ipi(uint32_t dst) __attribute__((always_inline));
44
45 void flush_windows();
46
47 #define store_alternate(addr,asi,data) ({ uint32_t __my_addr = (addr); uint32_t __my_data = (data); __asm__ __volatile__ ("sta %0,[%1] %2" : : "r"(__my_data),"r"(__my_addr),"i"(asi)); })
48 #define load_alternate(addr,asi) ({ uint32_t __my_addr = (addr); uint32_t __my_data; __asm__ __volatile__ ("lda [%1] %2,%0" : "=r"(__my_data) : "r"(__my_addr),"i"(asi)); __my_data; })
49
50 static __inline uint32_t
51 read_psr(void)
52 {
53         uint32_t reg;
54         asm volatile ("mov %%psr,%0" : "=r"(reg));
55         return reg;
56 }
57
58 static __inline uint32_t
59 read_wim(void)
60 {
61         uint32_t reg;
62         asm volatile ("mov %%wim,%0" : "=r"(reg));
63         return reg;
64 }
65
66 static __inline uint32_t
67 read_tbr(void)
68 {
69         uint32_t reg;
70         asm volatile ("mov %%tbr,%0" : "=r"(reg));
71         return reg;
72 }
73
74 static __inline uint32_t
75 read_mmu_reg(uint32_t which)
76 {
77         return load_alternate(which,4);
78 }
79
80 static __inline uint32_t
81 read_y(void)
82 {
83         uint32_t reg;
84         asm volatile ("mov %%y,%0" : "=r"(reg));
85         return reg;
86 }
87
88 static __inline uint32_t
89 read_fsr(void)
90 {
91         uint32_t reg;
92         asm volatile ("st %%fsr,%0" : "=m"(reg));
93         return reg;
94 }
95
96 static __inline void
97 write_psr(uint32_t val)
98 {
99         asm volatile ("mov %0,%%psr; nop;nop;nop" : : "r"(val) : "memory");
100 }
101
102 static __inline void
103 write_wim(uint32_t val)
104 {
105         asm volatile ("mov %0,%%wim; nop;nop;nop" : : "r"(val) : "memory");
106 }
107
108 static __inline void
109 write_tbr(uint32_t val)
110 {
111         asm volatile ("mov %0,%%tbr; nop;nop;nop" : : "r"(val) : "memory");
112 }
113
114 static __inline void
115 write_mmu_reg(uint32_t which, uint32_t val)
116 {
117         store_alternate(which,4,val);
118 }
119
120 static __inline void
121 write_y(uint32_t val)
122 {
123         asm volatile ("mov %0,%%y; nop;nop;nop" : : "r"(val) : "memory");
124 }
125
126 static __inline void
127 write_fsr(uint32_t val)
128 {
129         asm volatile ("ld %0,%%fsr; nop;nop;nop" : : "m"(val) : "memory");
130 }
131
132 static __inline uint32_t
133 memsize_mb(void)
134 {
135         uint32_t reg;
136         __asm__ __volatile__("mov %" XSTR(MEMSIZE_MB_REG) ",%0" : "=r"(reg));
137         return reg;
138 }
139
140 static __inline uint32_t
141 num_cores(void)
142 {
143         uint32_t reg;
144         __asm__ __volatile__("mov %" XSTR(NUM_CORES_REG) ",%0" : "=r"(reg));
145         return reg;
146 }
147
148 static __inline uint32_t
149 mmu_probe(uint32_t va)
150 {
151         return load_alternate((va & ~0xFFF) | 0x400, 3);
152 }
153
154 static __inline void
155 store_iobus(uint32_t device, uint32_t addr, uint32_t data)
156 {
157         #ifdef ROS_KERNEL
158                 store_alternate(device << 16 | addr, 2, data);
159         #else
160                 register uint32_t __my_addr asm("o0") = (addr);
161                 register uint32_t __my_data asm("o1") = (data);
162                 __asm__ __volatile__ ("ta 11" : : "r"(__my_addr),"r"(__my_data));
163         #endif
164 }
165
166 static __inline uint32_t
167 load_iobus(uint32_t device, uint32_t addr)
168 {
169         #ifdef ROS_KERNEL
170                 return load_alternate(device << 16 | addr, 2);
171         #else
172                 register uint32_t __my_addr asm("o0") = (addr);
173                 __asm__ __volatile__ ("ta 10" : "=r"(__my_addr) : "0"(__my_addr));
174                 return __my_addr;
175         #endif
176 }
177
178 static __inline uint32_t
179 send_ipi(uint32_t dst)
180 {
181         store_iobus(2,dst<<10,0);
182         return 0;
183 }
184
185 // arm the calling core's interrupt timer.
186 // enable must be 1 or 0; clocks must be a power of 2
187 static __inline void
188 sparc_set_timer(uint32_t clocks, uint32_t enable)
189 {
190         store_iobus(1,0,enable << TIMER_PERIOD_BITS | (clocks-1));
191 }
192
193 #endif /* !__ASSEMBLER__ */
194
195 #endif /* !ROS_INC_X86_H */