x86 core_id() uses the LAPIC again
[akaros.git] / kern / arch / i386 / arch.h
1 #ifndef ROS_INC_ARCH_H
2 #define ROS_INC_ARCH_H
3
4 #include <arch/x86.h>
5 #include <arch/types.h>
6 #include <arch/apic.h>
7 #include <arch/trap.h>
8
9 /* Arch Constants */
10 #define MAX_NUM_CPUS                            255
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 uint64_t read_tsc(void) __attribute__((always_inline));
16 static __inline uint64_t read_tsc_serialized(void) __attribute__((always_inline));
17 static __inline void enable_irq(void) __attribute__((always_inline));
18 static __inline void disable_irq(void) __attribute__((always_inline));
19 static __inline void enable_irqsave(int8_t* state) __attribute__((always_inline));
20 static __inline void disable_irqsave(int8_t* state) __attribute__((always_inline));
21 static __inline void cpu_relax(void) __attribute__((always_inline));
22 static __inline void cpu_halt(void) __attribute__((always_inline));
23 static __inline void clflush(uintptr_t* addr) __attribute__((always_inline));
24 static __inline int irq_is_enabled(void) __attribute__((always_inline));
25 static __inline uint32_t core_id(void) __attribute__((always_inline));
26 static __inline void cache_flush(void) __attribute__((always_inline));
27 static __inline void reboot(void) __attribute__((always_inline)) __attribute__((noreturn));
28
29 void print_cpuinfo(void);
30 void show_mapping(uintptr_t start, size_t size);
31 void backtrace(void);
32
33 static __inline void
34 breakpoint(void)
35 {
36         __asm __volatile("int3");
37 }
38
39 static __inline void 
40 invlpg(void *addr)
41
42         __asm __volatile("invlpg (%0)" : : "r" (addr) : "memory");
43 }  
44
45 static __inline void
46 tlbflush(void)
47 {
48         uint32_t cr3;
49         __asm __volatile("movl %%cr3,%0" : "=r" (cr3));
50         __asm __volatile("movl %0,%%cr3" : : "r" (cr3));
51 }
52
53 static __inline uint64_t
54 read_tsc(void)
55 {
56         uint64_t tsc;
57         __asm __volatile("rdtsc" : "=A" (tsc));
58         return tsc;
59 }
60
61 static __inline uint64_t 
62 read_tsc_serialized(void)
63 {
64     uint64_t tsc;
65         cpuid(0, 0, 0, 0, 0);
66         tsc = read_tsc();
67         return tsc;
68 }
69
70 static __inline void
71 enable_irq(void)
72 {
73         asm volatile("sti");
74 }
75
76 static __inline void
77 disable_irq(void)
78 {
79         asm volatile("cli");
80 }
81
82 static __inline void
83 enable_irqsave(int8_t* state)
84 {
85         // *state tracks the number of nested enables and disables
86         // initial value of state: 0 = first run / no favorite
87         // > 0 means more enabled calls have been made
88         // < 0 means more disabled calls have been made
89         // Mostly doing this so we can call disable_irqsave first if we want
90
91         // one side or another "gets a point" if interrupts were already the
92         // way it wanted to go.  o/w, state stays at 0.  if the state was not 0
93         // then, enabling/disabling isn't even an option.  just increment/decrement
94
95         // if enabling is winning or tied, make sure it's enabled
96         if ((*state == 0) && !irq_is_enabled())
97                 enable_irq();
98         else
99                 (*state)++;
100 }
101
102 static __inline void
103 disable_irqsave(int8_t* state)
104 {
105         if ((*state == 0) && irq_is_enabled())
106                 disable_irq();
107         else 
108                 (*state)--;
109 }
110
111 static __inline void
112 cpu_relax(void)
113 {
114         // in case the compiler doesn't serialize for pause, the "m" will make sure
115         // no memory is reordered around this instruction.
116         asm volatile("pause" : : : "memory");
117 }
118
119 static __inline void
120 cpu_halt(void)
121 {
122         asm volatile("hlt" : : : "memory");
123 }
124
125 static __inline void
126 clflush(uintptr_t* addr) __attribute__((always_inline))
127 {
128         asm volatile("clflush %0" : : "m"(*addr));
129 }
130
131 static __inline int
132 irq_is_enabled(void)
133 {
134         return read_eflags() & FL_IF;
135 }
136
137 static __inline uint32_t
138 core_id(void)
139 {
140         return lapic_get_id();
141 }
142
143 static __inline void
144 cache_flush(void)
145 {
146         wbinvd();
147 }
148
149 static __inline void
150 reboot(void)
151 {
152         outb(0x92, 0x3);
153         asm volatile ("movl $0, %esp; int $0");
154         while(1);
155 }
156
157 #endif /* !ROS_INC_X86_H */