Active messages using dynamically allocated memory
[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 <ros/common.h>
6 #include <arch/trap.h>
7 #include <arch/apic.h>
8
9 /* Arch Constants */
10 #define MAX_NUM_CPUS                            255
11 #define HW_CACHE_ALIGN                           64
12
13 static __inline void breakpoint(void) __attribute__((always_inline));
14 static __inline void invlpg(void *SNT addr) __attribute__((always_inline));
15 static __inline void tlbflush(void) __attribute__((always_inline));
16 static __inline uint64_t read_tsc(void) __attribute__((always_inline));
17 static __inline uint64_t read_tsc_serialized(void) __attribute__((always_inline));
18 static __inline void enable_irq(void) __attribute__((always_inline));
19 static __inline void disable_irq(void) __attribute__((always_inline));
20 static __inline void enable_irqsave(int8_t* state) __attribute__((always_inline));
21 static __inline void disable_irqsave(int8_t* state) __attribute__((always_inline));
22 static __inline void cpu_relax(void) __attribute__((always_inline));
23 static __inline void cpu_halt(void) __attribute__((always_inline));
24 static __inline void clflush(uintptr_t* addr) __attribute__((always_inline));
25 static __inline int irq_is_enabled(void) __attribute__((always_inline));
26 static __inline uint32_t core_id(void) __attribute__((always_inline));
27 static __inline void cache_flush(void) __attribute__((always_inline));
28 static __inline void reboot(void) __attribute__((always_inline)) __attribute__((noreturn));
29
30 void print_cpuinfo(void);
31 void show_mapping(uintptr_t start, size_t size);
32 void backtrace(void);
33
34 static __inline void
35 breakpoint(void)
36 {
37         __asm __volatile("int3");
38 }
39
40 static __inline void 
41 invlpg(void *addr)
42
43         __asm __volatile("invlpg (%0)" : : "r" (addr) : "memory");
44 }  
45
46 static __inline void
47 tlbflush(void)
48 {
49         uint32_t cr3;
50         __asm __volatile("movl %%cr3,%0" : "=r" (cr3));
51         __asm __volatile("movl %0,%%cr3" : : "r" (cr3));
52 }
53
54 static __inline uint64_t
55 read_tsc(void)
56 {
57         uint64_t tsc;
58         __asm __volatile("rdtsc" : "=A" (tsc));
59         return tsc;
60 }
61
62 static __inline uint64_t 
63 read_tsc_serialized(void)
64 {
65     uint64_t tsc;
66         cpuid(0, 0, 0, 0, 0);
67         tsc = read_tsc();
68         return tsc;
69 }
70
71 static __inline void
72 enable_irq(void)
73 {
74         asm volatile("sti");
75 }
76
77 static __inline void
78 disable_irq(void)
79 {
80         asm volatile("cli");
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         __cpu_relax();
116 }
117
118 static __inline void
119 cpu_halt(void)
120 {
121         asm volatile("hlt" : : : "memory");
122 }
123
124 static __inline void
125 clflush(uintptr_t* addr)
126 {
127         asm volatile("clflush %0" : : "m"(*addr));
128 }
129
130 static __inline int
131 irq_is_enabled(void)
132 {
133         return read_eflags() & FL_IF;
134 }
135
136 static __inline uint32_t
137 core_id(void)
138 {
139         return lapic_get_id();
140 }
141
142 static __inline void
143 cache_flush(void)
144 {
145         wbinvd();
146 }
147
148 static __inline void
149 reboot(void)
150 {
151         outb(0x92, 0x3);
152         asm volatile ("movl $0, %esp; int $0");
153         while(1);
154 }
155
156 #endif /* !ROS_INC_ARCH_H */