Changes ARCH i686 -> x86 (XCC)
[akaros.git] / kern / arch / x86 / arch.h
1 #ifndef ROS_INC_ARCH_H
2 #define ROS_INC_ARCH_H
3
4 #include <ros/arch/arch.h>
5 #include <ros/common.h>
6 #include <arch/x86.h>
7 #include <arch/apic.h>
8
9 /* Arch Constants */
10 #define ARCH_CL_SIZE                             64
11 /* Top of the kernel virtual mapping area (KERNBASE) */
12 /* For sanity reasons, I don't plan to map the top page */
13 #define KERN_VMAP_TOP                           0xfffff000
14
15 static __inline void breakpoint(void) __attribute__((always_inline));
16 static __inline void invlpg(void *SNT addr) __attribute__((always_inline));
17 static __inline void tlbflush(void) __attribute__((always_inline));
18 static __inline void icache_flush_page(void* va, void* kva) __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 int get_hw_coreid(uint32_t coreid);
30 static __inline int hw_core_id(void) __attribute__((always_inline));
31 static __inline int get_os_coreid(int hw_coreid);
32 static __inline int core_id(void) __attribute__((always_inline));
33 static __inline void cache_flush(void) __attribute__((always_inline));
34 static __inline void reboot(void) __attribute__((always_inline)) __attribute__((noreturn));
35
36 /* in trap.c */
37 void send_ipi(uint32_t os_coreid, uint8_t vector);
38 /* in cpuinfo.c */
39 void print_cpuinfo(void);
40 void show_mapping(uintptr_t start, size_t size);
41
42 /* declared in smp.c */
43 int hw_coreid_lookup[MAX_NUM_CPUS];
44 int os_coreid_lookup[MAX_NUM_CPUS];
45
46 static __inline void
47 breakpoint(void)
48 {
49         __asm __volatile("int3");
50 }
51
52 static __inline void 
53 invlpg(void *addr)
54
55         __asm __volatile("invlpg (%0)" : : "r" (addr) : "memory");
56 }  
57
58 static __inline void
59 tlbflush(void)
60 {
61         uint32_t cr3;
62         __asm __volatile("movl %%cr3,%0" : "=r" (cr3));
63         __asm __volatile("movl %0,%%cr3" : : "r" (cr3));
64 }
65
66 static __inline void
67 icache_flush_page(void* va, void* kva)
68 {
69         // x86 handles self-modifying code (mostly) without SW support
70 }
71
72 static __inline uint64_t
73 read_tsc(void)
74 {
75         uint64_t tsc;
76         __asm __volatile("rdtsc" : "=A" (tsc));
77         return tsc;
78 }
79
80 /* non-core-id reporting style (it is in ecx) */
81 static __inline uint64_t
82 read_tscp(void)
83 {
84         uint64_t tsc;
85         __asm __volatile("rdtscp" : "=A" (tsc) : : "ecx");
86         return tsc;
87 }
88
89 /* Check out k/a/x86/rdtsc_test.c for more info */
90 static __inline uint64_t 
91 read_tsc_serialized(void)
92 {
93         asm volatile("lfence"); /* mfence on amd */
94         return read_tsc();
95 }
96
97 static __inline void
98 enable_irq(void)
99 {
100         asm volatile("sti");
101 }
102
103 static __inline void
104 disable_irq(void)
105 {
106         asm volatile("cli");
107 }
108
109 static __inline void
110 enable_irqsave(int8_t* state)
111 {
112         // *state tracks the number of nested enables and disables
113         // initial value of state: 0 = first run / no favorite
114         // > 0 means more enabled calls have been made
115         // < 0 means more disabled calls have been made
116         // Mostly doing this so we can call disable_irqsave first if we want
117
118         // one side or another "gets a point" if interrupts were already the
119         // way it wanted to go.  o/w, state stays at 0.  if the state was not 0
120         // then, enabling/disabling isn't even an option.  just increment/decrement
121
122         // if enabling is winning or tied, make sure it's enabled
123         if ((*state == 0) && !irq_is_enabled())
124                 enable_irq();
125         else
126                 (*state)++;
127 }
128
129 static __inline void
130 disable_irqsave(int8_t* state)
131 {
132         if ((*state == 0) && irq_is_enabled())
133                 disable_irq();
134         else 
135                 (*state)--;
136 }
137
138 static __inline void
139 cpu_relax(void)
140 {
141         __cpu_relax();
142 }
143
144 /* This doesn't atomically enable interrupts and then halt, like we want, so
145  * x86 needs to use a custom helper in the irq handler in trap.c. */
146 static __inline void
147 cpu_halt(void)
148 {
149         asm volatile("sti; hlt" : : : "memory");
150 }
151
152 static __inline void
153 clflush(uintptr_t* addr)
154 {
155         asm volatile("clflush %0" : : "m"(*addr));
156 }
157
158 static __inline int
159 irq_is_enabled(void)
160 {
161         return read_eflags() & FL_IF;
162 }
163
164 /* os_coreid -> hw_coreid */
165 static __inline int
166 get_hw_coreid(uint32_t coreid)
167 {
168         return hw_coreid_lookup[coreid];
169 }
170
171 static __inline int
172 hw_core_id(void)
173 {
174         return lapic_get_id();
175 }
176
177 /* hw_coreid -> os_coreid */
178 static __inline int
179 get_os_coreid(int hw_coreid)
180 {
181         return os_coreid_lookup[hw_coreid];
182 }
183
184 /* core_id() returns the OS core number, not to be confused with the
185  * hardware-specific core identifier (such as the lapic id) returned by
186  * hw_core_id() */
187 static __inline int
188 core_id(void)
189 {
190         return get_os_coreid(hw_core_id());
191 }
192
193 static __inline void
194 cache_flush(void)
195 {
196         wbinvd();
197 }
198
199 static __inline void
200 reboot(void)
201 {
202         outb(0x92, 0x3);
203         asm volatile ("movl $0, %esp; int $0");
204         while(1);
205 }
206
207 #endif /* !ROS_INC_ARCH_H */