Remove the old console input code; use qio
[akaros.git] / kern / src / colored_caches.c
1 /* Copyright (c) 2009 The Regents of the University  of California.
2  * See the COPYRIGHT files at the top of this source tree for full
3  * license information.
4  *
5  * Kevin Klues <klueska@cs.berkeley.edu>
6  */
7
8 #include <ros/common.h>
9 #include <arch/mmu.h>
10 #include <bitmask.h>
11 #include <colored_caches.h>
12 #include <stdio.h>
13 #include <atomic.h>
14 #include <kmalloc.h>
15 #include <page_alloc.h>
16
17 #define l1 (available_caches.l1)
18 #define l2 (available_caches.l2)
19 #define l3 (available_caches.l3)
20
21 spinlock_t cache_colors_lock = SPINLOCK_INITIALIZER_IRQSAVE;
22
23 /************** Cache Related Functions  *****************/
24 inline void init_cache_properties(cache_t *c, size_t sz_k, size_t wa, size_t clsz) {
25         c->wa = wa;
26         c->sz_k = sz_k;
27         c->clsz = clsz;
28
29 #ifdef CONFIG_PAGE_COLORING
30         //Added as optimization (derived from above);
31         size_t nc = get_cache_num_page_colors(c);
32         c->num_colors = nc;
33 #else
34         c->num_colors = 1;
35 #endif
36 }
37
38 inline void init_free_cache_colors_map(cache_t* c)
39 {
40         // Initialize the free colors map
41         c->free_colors_map = kmalloc(c->num_colors, 0);
42         FILL_BITMASK(c->free_colors_map, c->num_colors);
43 }
44
45 inline size_t get_offset_in_cache_line(uintptr_t addr, cache_t *c) {
46     return (addr % get_cache_bytes_per_line(c));
47 }
48
49 void print_cache_properties(char *lstring, cache_t *c)
50 {
51         printk("%s_WAYS_ASSOCIATIVE: %ld\n", lstring, get_cache_ways_associative(c));
52         printk("%s_LINE_SIZE_BYTES: %ld\n", lstring, get_cache_line_size_bytes(c));
53         printk("%s_SIZE_BYTES: %ld\n", lstring, get_cache_size_bytes(c));
54         printk("%s_SIZE_KILOBYTES: %ld\n", lstring, get_cache_size_kilobytes(c));
55         printk("%s_SIZE_MEGABYTES: %ld\n", lstring, get_cache_size_megabytes(c));
56         printk("%s_OFFSET_BITS: %ld\n", lstring, get_cache_num_offset_bits(c));
57         printk("%s_INDEX_BITS: %ld\n", lstring, get_cache_num_index_bits(c));
58         printk("%s_TAG_BITS: %ld\n", lstring, get_cache_num_tag_bits(c));
59         printk("%s_PAGE_COLOR_BITS: %ld\n", lstring, get_cache_num_page_color_bits(c));
60         printk("%s_BYTES_PER_LINE: %ld\n", lstring, get_cache_bytes_per_line(c));
61         printk("%s_NUM_LINES: %ld\n", lstring, get_cache_num_lines(c));
62         printk("%s_NUM_SETS: %ld\n", lstring, get_cache_num_sets(c));
63         printk("%s_LINES_PER_SET: %ld\n", lstring, get_cache_lines_per_set(c));
64         printk("%s_LINES_PER_PAGE: %ld\n", lstring, get_cache_lines_per_page(c));
65         printk("%s_BYTES_PER_WAY: %ld\n", lstring, get_cache_bytes_per_way(c));
66         printk("%s_LINES_PER_WAY: %ld\n", lstring, get_cache_lines_per_way(c));
67         printk("%s_PAGES_PER_WAY: %ld\n", lstring, get_cache_pages_per_way(c));
68         printk("%s_NUM_PAGE_COLORS: %ld\n", lstring, get_cache_num_page_colors(c));
69 }
70
71 /****************** Cache Properties *********************/
72 inline size_t get_cache_ways_associative(cache_t *c) {
73         return (c->wa);
74 }
75 inline size_t get_cache_line_size_bytes(cache_t *c) {
76         return (c->clsz);
77 }
78 inline size_t get_cache_size_bytes(cache_t *c) {
79         return (c->sz_k * ONE_KILOBYTE);
80 }
81 inline size_t get_cache_size_kilobytes(cache_t *c) {
82         return (c->sz_k);
83 }
84 inline size_t get_cache_size_megabytes(cache_t *c) {
85         return (c->sz_k / ONE_KILOBYTE);
86 }
87 inline size_t get_cache_num_offset_bits(cache_t *c) {
88         return (LOG2_UP(get_cache_line_size_bytes(c)));
89 }
90 inline size_t get_cache_num_index_bits(cache_t *c) {
91         return (LOG2_UP(get_cache_size_bytes(c)
92                    / get_cache_ways_associative(c)
93                    / get_cache_line_size_bytes(c)));
94 }
95 inline size_t get_cache_num_tag_bits(cache_t *c) {
96         return (NUM_ADDR_BITS - get_cache_num_offset_bits(c)
97                           - get_cache_num_index_bits(c));
98 }
99 inline size_t get_cache_num_page_color_bits(cache_t *c) {
100         return (get_cache_num_offset_bits(c)
101                   + get_cache_num_index_bits(c)
102                   - PGSHIFT);
103 }
104 inline size_t get_cache_bytes_per_line(cache_t *c) {
105         return (1 << get_cache_num_offset_bits(c));
106 }
107 inline size_t get_cache_num_lines(cache_t *c) {
108         return (get_cache_size_bytes(c)/get_cache_bytes_per_line(c));
109 }
110 inline size_t get_cache_num_sets(cache_t *c) {
111         return (get_cache_num_lines(c)/get_cache_ways_associative(c));
112 }
113 inline size_t get_cache_lines_per_set(cache_t *c) {
114         return (get_cache_ways_associative(c));
115 }
116 inline size_t get_cache_lines_per_page(cache_t *c) {
117         return (PGSIZE / get_cache_bytes_per_line(c));
118 }
119 inline size_t get_cache_bytes_per_way(cache_t *c) {
120         return (get_cache_size_bytes(c)/get_cache_ways_associative(c));
121 }
122 inline size_t get_cache_lines_per_way(cache_t *c) {
123         return (get_cache_num_lines(c)/get_cache_ways_associative(c));
124 }
125 inline size_t get_cache_pages_per_way(cache_t *c) {
126         return (get_cache_lines_per_way(c)/get_cache_lines_per_page(c));
127 }
128 inline size_t get_cache_num_page_colors(cache_t *c) {
129         return get_cache_pages_per_way(c);
130 }
131
132 static inline void set_color_range(uint16_t color, uint8_t* map,
133                                    cache_t* smaller, cache_t* bigger)
134 {
135         size_t base, r;
136         if(smaller->num_colors <= bigger->num_colors) {
137                 r = bigger->num_colors / smaller->num_colors;
138                 base = color*r;
139                 SET_BITMASK_RANGE(map, base, base+r);
140         }
141         else {
142                 r = smaller->num_colors / bigger->num_colors;
143                 base = color/r;
144                 if(BITMASK_IS_SET_IN_RANGE(smaller->free_colors_map,
145                                            base*r, base*r+r-1))
146                         SET_BITMASK_BIT(map, base);
147         }
148 }
149
150 static inline void clr_color_range(uint16_t color, uint8_t* map,
151                                    cache_t* smaller, cache_t* bigger)
152 {
153         size_t base, r;
154         if(smaller->num_colors <= bigger->num_colors) {
155                 r = bigger->num_colors / smaller->num_colors;
156                 base = color*r;
157                 CLR_BITMASK_RANGE(map, base, base+r);
158         }
159         else {
160                 r = smaller->num_colors / bigger->num_colors;
161                 base = color/r;
162                 CLR_BITMASK_BIT(map, base);
163         }
164 }
165
166 static inline error_t __cache_color_alloc_specific(size_t color, cache_t* c,
167                                                          uint8_t* colors_map)
168 {
169         if(!GET_BITMASK_BIT(c->free_colors_map, color))
170                 return -ENOCACHE;
171
172         if(l1)
173                 clr_color_range(color, l1->free_colors_map, c, l1);
174         if(l2)
175                 clr_color_range(color, l2->free_colors_map, c, l2);
176         if(l3)
177                 clr_color_range(color, l3->free_colors_map, c, l3);
178
179         set_color_range(color, colors_map, c, llc_cache);
180         return ESUCCESS;
181 }
182
183 static inline error_t __cache_color_alloc(cache_t* c, uint8_t* colors_map)
184 {
185         if(BITMASK_IS_CLEAR(c->free_colors_map, c->num_colors))
186                 return -ENOCACHE;
187
188         int color=0;
189         do {
190                 if(GET_BITMASK_BIT(c->free_colors_map, color))
191                         break;
192         } while(++color);
193
194         return __cache_color_alloc_specific(color, c, colors_map);
195 }
196
197 static inline void __cache_color_free_specific(size_t color, cache_t* c,
198                                                      uint8_t* colors_map)
199 {
200         if(GET_BITMASK_BIT(c->free_colors_map, color))
201                 return;
202         else {
203                 size_t r = llc_cache->num_colors / c->num_colors;
204                 size_t base = color*r;
205                 if(!BITMASK_IS_SET_IN_RANGE(colors_map, base, base+r))
206                         return;
207         }
208
209         if(l3)
210                 set_color_range(color, l3->free_colors_map, c, l3);
211         if(l2)
212                 set_color_range(color, l2->free_colors_map, c, l2);
213         if(l1)
214                 set_color_range(color, l1->free_colors_map, c, l1);
215
216         clr_color_range(color, colors_map, c, llc_cache);
217 }
218
219 static inline void __cache_color_free(cache_t* c, uint8_t* colors_map)
220 {
221         if(BITMASK_IS_FULL(c->free_colors_map, c->num_colors))
222                 return;
223
224         int color=0;
225         do {
226                 if(!GET_BITMASK_BIT(c->free_colors_map, color)) {
227                         size_t r = llc_cache->num_colors / c->num_colors;
228                         size_t base = color*r;
229                         if(BITMASK_IS_SET_IN_RANGE(colors_map, base, base+r))
230                                 break;
231                 }
232         } while(++color < c->num_colors);
233         if(color == c->num_colors)
234                 return;
235
236         __cache_color_free_specific(color, c, colors_map);
237 }
238
239 uint8_t* cache_colors_map_alloc() {
240 #ifdef CONFIG_PAGE_COLORING
241         uint8_t* colors_map = kmalloc(llc_cache->num_colors, 0);
242         if(colors_map)
243                 CLR_BITMASK(colors_map, llc_cache->num_colors);
244         return colors_map;
245 #else
246         return global_cache_colors_map;
247 #endif
248 }
249
250 void cache_colors_map_free(uint8_t* colors_map) {
251 #ifdef CONFIG_PAGE_COLORING
252         kfree(colors_map);
253 #endif
254 }
255
256 error_t cache_color_alloc(cache_t* c, uint8_t* colors_map)
257 {
258         spin_lock_irqsave(&cache_colors_lock);
259         error_t e = __cache_color_alloc(c, colors_map);
260         spin_unlock_irqsave(&cache_colors_lock);
261         return e;
262 }
263 error_t cache_color_alloc_specific(size_t color, cache_t* c, uint8_t* colors_map)
264 {
265         spin_lock_irqsave(&cache_colors_lock);
266         error_t e = __cache_color_alloc_specific(color, c, colors_map);
267         spin_unlock_irqsave(&cache_colors_lock);
268         return e;
269 }
270
271 void cache_color_free(cache_t* c, uint8_t* colors_map)
272 {
273         spin_lock_irqsave(&cache_colors_lock);
274         __cache_color_free(c, colors_map);
275         spin_unlock_irqsave(&cache_colors_lock);
276 }
277 void cache_color_free_specific(size_t color, cache_t* c, uint8_t* colors_map)
278 {
279         spin_lock_irqsave(&cache_colors_lock);
280         __cache_color_free_specific(color, c, colors_map);
281         spin_unlock_irqsave(&cache_colors_lock);
282 }
283