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