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