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