Added FPU emulation to SPARC port
[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 extern uintptr_t mmu_context_tables[MAX_NUM_CPUS][NCONTEXTS+CONTEXT_TABLE_PAD];
39
40 static __inline void
41 breakpoint(void)
42 {
43         __asm __volatile("ta 0x7f");
44 }
45
46 static __inline void 
47 invlpg(void *addr)
48
49         store_alternate(((intptr_t)addr) & ~0xFFF,3,0);
50 }  
51
52 static __inline void
53 tlbflush(void)
54 {
55         // unsure if we'll support this yet...
56         // may have to just do invlpg() in a loop
57         store_alternate(0x400,3,0);
58 }
59
60 static __inline uint64_t
61 read_tsc(void)
62 {
63         return read_perfctr(0,0);
64 }
65
66 static __inline uint64_t 
67 read_tsc_serialized(void)
68 {
69         return read_tsc();
70 }
71
72 static __inline void
73 enable_irq(void)
74 {
75         write_psr(read_psr() & ~0xF00);
76 }
77
78 static __inline void
79 disable_irq(void)
80 {
81         write_psr(read_psr() | 0xF00);
82 }
83
84 static __inline void
85 enable_irqsave(int8_t* state)
86 {
87         // *state tracks the number of nested enables and disables
88         // initial value of state: 0 = first run / no favorite
89         // > 0 means more enabled calls have been made
90         // < 0 means more disabled calls have been made
91         // Mostly doing this so we can call disable_irqsave first if we want
92
93         // one side or another "gets a point" if interrupts were already the
94         // way it wanted to go.  o/w, state stays at 0.  if the state was not 0
95         // then, enabling/disabling isn't even an option.  just increment/decrement
96
97         // if enabling is winning or tied, make sure it's enabled
98         if ((*state == 0) && !irq_is_enabled())
99                 enable_irq();
100         else
101                 (*state)++;
102 }
103
104 static __inline void
105 disable_irqsave(int8_t* state)
106 {
107         if ((*state == 0) && irq_is_enabled())
108                 disable_irq();
109         else 
110                 (*state)--;
111 }
112
113 static __inline void
114 cpu_relax(void)
115 {
116         int ctr = 8;
117         asm volatile("1: deccc %0; bne 1b; nop" :
118                      "=r"(ctr) : "0"(ctr) : "cc","memory");
119 }
120
121 static __inline void
122 cpu_halt(void)
123 {
124         asm volatile("1: ba 1b; nop" : : : "memory");
125 }
126
127 static __inline void
128 clflush(uintptr_t* addr)
129 {
130         asm volatile("flush %0" : : "r"(addr));
131 }
132
133 static __inline int
134 irq_is_enabled(void)
135 {
136         return (read_psr() & 0xF00) == 0;
137 }
138
139 static __inline uint32_t
140 core_id(void)
141 {
142         uint32_t reg;
143         __asm__ __volatile__("mov %" XSTR(CORE_ID_REG) ",%0" : "=r"(reg));
144         return reg;
145 }
146
147 static __inline void
148 cache_flush(void)
149 {
150 }
151
152 static __inline void
153 reboot(void)
154 {
155         extern void appserver_die(int code);
156         appserver_die(0);
157         while(1);
158 }
159
160 static __inline void
161 lcr3(uint32_t val)
162 {
163         mmu_context_tables[core_id()][0] = val >> 4 | PTE_PTD;
164         tlbflush();
165 }
166
167 static __inline uint32_t
168 rcr3(void)
169 {
170         return (mmu_context_tables[core_id()][0] & ~0x3) << 4;
171 }
172
173 #endif /* !__ASSEMBLER__ */
174
175 #endif /* !ROS_INC_X86_H */