Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Cache partitioning support
[palacios.git] / palacios / src / palacios / vmm_cachepart.c
1 /* 
2  * This file is part of the Palacios Virtual Machine Monitor developed
3  * by the V3VEE Project with funding from the United States National 
4  * Science Foundation and the Department of Energy.  
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at 
8  * http://www.v3vee.org
9  *
10  * Copyright (c) 2015, The V3VEE Project <http://www.v3vee.org> 
11  * All rights reserved.
12  *
13  * Author:  Peter Dinda <pdinda@northwestern.edu>
14  *
15  * This is free software.  You are permitted to use,
16  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
17  */
18
19 #include <palacios/vmm.h>
20 #include <palacios/vm_guest.h>
21 #include <interfaces/vmm_cache_info.h>
22
23 #ifndef V3_CONFIG_DEBUG_CACHEPART
24 #undef PrintDebug
25 #define PrintDebug(fmt, args...)
26 #endif
27
28 /*
29
30   <cachepart 
31         block_size=BLOCK_SIZE 
32         num_colors=NUM_COLORS
33         min_color=MIN_COLOR
34         max_color=MAX_COLOR />
35
36   Cache partitioning support
37
38   We are partioning the last level shared cache here. 
39
40   Cache partitioning is applied to the guest physical memory allocation
41   and page allocations for nested and shadow paging.   To the extent
42   possible, we also try to apply this paritioning to other allocations
43   and as early as possible during the creation of the VM
44
45   BLOCK_SIZE      =  required v3_mem_block_size needed for partitioning in bytes
46                      this is typically one page (4096 bytes)
47   NUM_COLORS      =  the number of page colors the cache is expected to hold
48                      this is used to make the min/max color fields sensible
49   [MIN_COLOR,MAX_COLOR]
50                   =  the range of allowed page colors allowed for this VM
51                      with respect to the range [0,NUMCOLORS)
52 */
53
54 static int inited=0;    
55 static struct v3_cache_info cache_info;
56
57 #define CEIL_DIV(x,y) (((x)/(y)) + !!((x)%(y)))
58 #define FLOOR_DIV(x,y) (((x)/(y)))
59 #define DIVIDES(x,y) (!((x)%(y)))
60
61                  
62 static inline int getcacheinfo() 
63 {
64     if (inited) {
65         return 0;
66     } else {
67         if (v3_get_cache_info(V3_CACHE_COMBINED,0xffffffff,&cache_info)) { 
68             PrintError(VM_NONE,VCORE_NONE,"Unable to get information about cache\n");
69             return -1;
70         }
71         V3_Print(VM_NONE,VCORE_NONE,"cachepart: last level combined cache: 0x%x bytes, 0x%x blocksize, 0x%x associativity\n",cache_info.size,cache_info.blocksize,cache_info.associativity);
72         inited=1;
73         if (!(DIVIDES(cache_info.size,cache_info.blocksize) &&
74               DIVIDES(cache_info.size,cache_info.associativity) &&
75               DIVIDES(cache_info.size/cache_info.blocksize,cache_info.associativity))) {
76             PrintError(VM_NONE,VCORE_NONE,"cachepart: CACHE INFO IS NONSENSICAL\n");
77             return -1;
78         }
79         return 0;
80     }
81 }
82
83 int v3_init_cachepart()
84 {
85     PrintDebug(VM_NONE,VCORE_NONE,"cachepart: init\n");
86     return 0;
87 }
88
89 int v3_deinit_cachepart()
90 {
91     PrintDebug(VM_NONE,VCORE_NONE,"cachepart: deinit\n");
92     return 0;
93 }
94
95 /*
96 static int bitcount(uint64_t x)
97 {
98     int c=0;
99
100     while (x) {
101         c+=x&0x1;
102         x>>=1;
103     }
104     return c;
105 }
106
107 static int is_pow2(x)
108 {
109     int c = bitcount(x);
110
111     return c==0 || c==1;
112 }
113 */
114
115 static uint64_t log2(uint64_t x)
116 {
117     uint64_t i=-1;
118     
119     while (x) { 
120         i++;
121         x>>=1;
122     }
123
124     return i;
125 }
126
127 static uint64_t pow2(uint64_t n)
128 {
129     uint64_t x = 1;
130     while (n) {
131         x*=2;
132         n--;
133     }
134     return x;
135 }
136
137 static uint64_t num_lines()
138 {
139     return FLOOR_DIV(cache_info.size,cache_info.blocksize);
140 }
141
142 static uint64_t num_sets()
143 {
144     return FLOOR_DIV(num_lines(),cache_info.associativity);
145 }
146
147
148 static void build_colors(v3_cachepart_t *c)
149 {
150     uint64_t bo_bits, set_bits, bs_bits;
151     
152     // number of bits in block offset
153     bo_bits = log2(cache_info.blocksize);
154     set_bits = log2(num_sets());
155     bs_bits = log2(c->mem_block_size);
156     
157     if (bs_bits<bo_bits || bs_bits >= (bo_bits+set_bits)) { 
158         c->actual_num_colors = 1;
159         c->color_mask=0;
160         c->color_shift=0;
161         c->min_color=0;
162         c->max_color=0;
163     } else {
164         c->actual_num_colors = pow2(bo_bits+set_bits-bs_bits);
165         c->color_mask = (c->actual_num_colors-1);
166         c->color_shift = bs_bits;
167         c->min_color = FLOOR_DIV(c->min_color,CEIL_DIV(c->expected_num_colors,c->actual_num_colors));
168         c->max_color = FLOOR_DIV(c->max_color,CEIL_DIV(c->expected_num_colors,c->actual_num_colors));
169     }
170 }
171
172 int v3_init_cachepart_vm(struct v3_vm_info *vm, struct v3_xml *config)
173 {
174     extern uint64_t v3_mem_block_size;
175     v3_cfg_tree_t *cp;
176     char *block_size_s;
177     char *num_colors_s;
178     char *min_color_s;
179     char *max_color_s;
180     uint64_t req_block_size, req_num_colors, req_min_color, req_max_color;
181     v3_cachepart_t *c = &(vm->cachepart_state);
182
183     if (getcacheinfo()) { 
184         PrintError(VM_NONE,VCORE_NONE,"cachepart: getcacheinfo failed!\n");
185         return -1;
186     }
187
188     if (!config || !(cp=v3_cfg_subtree(config,"cachepart"))) { 
189         PrintDebug(vm,VCORE_NONE,"cachepart: no cachepart configuration found\n");
190         return 0;
191     }
192     
193     if (!(block_size_s=v3_cfg_val(cp,"block_size"))) { 
194         PrintError(vm,VCORE_NONE,"cachepart: missing block_size parameter\n");
195         return 0;
196     }
197
198     req_block_size = atoi(block_size_s);
199
200     if (!(num_colors_s=v3_cfg_val(cp,"num_colors"))) { 
201         PrintError(vm,VCORE_NONE,"cachepart: missing num_colors parameter\n");
202         return -1;
203     }
204     
205     req_num_colors=atoi(num_colors_s);
206
207     if (!(min_color_s=v3_cfg_val(cp,"min_color"))) { 
208         PrintError(vm,VCORE_NONE,"cachepart: missing min_color parameter\n");
209         return -1;
210     }
211
212     req_min_color=atoi(min_color_s);
213
214     if (!(max_color_s=v3_cfg_val(cp,"max_color"))) { 
215         PrintError(vm,VCORE_NONE,"cachepart: missing max_color parameter\n");
216         return -1;
217     }
218     
219     req_max_color=atoi(max_color_s);
220         
221     PrintDebug(vm,VCORE_NONE,"cachepart: request block_size=0x%llx, num_colors=0x%llx, min_color=0x%llx, max_color=0x%llx\n", req_block_size, req_num_colors, req_min_color, req_max_color);
222
223     if (req_block_size!=v3_mem_block_size) { 
224         PrintError(vm,VCORE_NONE,"cachepart: requested block size is %llu, but palacios is configured with v3_mem_block_size=%llu\n",req_block_size,v3_mem_block_size);
225         return -1;
226     }
227
228     if (req_max_color>=req_num_colors || req_min_color>req_max_color) {
229         PrintError(vm,VCORE_NONE,"cachepart: min/max color request is nonsensical\n");
230         return -1;
231     }
232     
233     memset(c,0,sizeof(*c));
234
235     c->mem_block_size=req_block_size;
236     c->expected_num_colors=req_num_colors;
237     c->min_color=req_min_color;
238     c->max_color=req_max_color;
239
240     // Now update the color structure to reflect the cache constraints
241     build_colors(c);
242
243
244     PrintDebug(vm,VCORE_NONE,"cachepart: cache has 0x%llx colors so finalized to block_size=0x%llx, num_colors=0x%llx, min_color=0x%llx, max_color=0x%llx, color_shift=0x%llx, color_mask=0x%llx\n", c->actual_num_colors, c->mem_block_size, c->actual_num_colors, c->min_color, c->max_color, c->color_shift, c->color_mask);
245
246     if (vm->resource_control.pg_filter_func || vm->resource_control.pg_filter_state) { 
247         PrintError(vm,VCORE_NONE, "cachepart: paging filter functions and state are already installed...\n");
248         return -1;
249     }
250     
251     vm->resource_control.pg_filter_func = (int (*)(void *,void*)) v3_cachepart_filter;
252     vm->resource_control.pg_filter_state = &vm->cachepart_state;
253
254
255     //    V3_Sleep(50000000);
256
257     return 0;
258     
259 }
260
261 int v3_deinit_cachepart_vm(struct v3_vm_info *vm)
262 {
263     // nothing to do
264     return 0;
265 }
266
267 int v3_init_cachepart_core(struct guest_info *core)
268 {
269     // nothing to do yet
270     return 0;
271 }
272
273 int v3_deinit_cachepart_core(struct guest_info *core)
274 {
275     // nothing to do yet
276     return 0;
277 }
278
279 static unsigned count=0;
280
281 int v3_cachepart_filter(void *paddr, v3_cachepart_t *c)
282 {
283     uint64_t a = (uint64_t)paddr;
284     uint64_t color = (a >> c->color_shift) & c->color_mask;
285
286     PrintDebug(VM_NONE,VCORE_NONE,"cachepart: %p is color 0x%llx required colors: [0x%llx,0x%llx] %s\n",paddr,color,c->min_color,c->max_color, color>=c->min_color && color<=c->max_color ? "ACCEPT" : "REJECT");
287
288     /*
289     if (count<10) { 
290         V3_Sleep(5000000);
291         count++;
292     }
293     */
294
295     return color>=c->min_color && color<=c->max_color;
296
297 }
298