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