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