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