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.


Assorted cleanup of memory-related user-level stuff
[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 uint64_t log2(uint64_t x)
97 {
98     uint64_t i=-1;
99     
100     while (x) { 
101         i++;
102         x>>=1;
103     }
104
105     return i;
106 }
107
108 static uint64_t pow2(uint64_t n)
109 {
110     uint64_t x = 1;
111     while (n) {
112         x*=2;
113         n--;
114     }
115     return x;
116 }
117
118 static uint64_t num_lines()
119 {
120     return FLOOR_DIV(cache_info.size,cache_info.blocksize);
121 }
122
123 static uint64_t num_sets()
124 {
125     return FLOOR_DIV(num_lines(),cache_info.associativity);
126 }
127
128
129 static void build_colors(v3_cachepart_t *c)
130 {
131     uint64_t bo_bits, set_bits, bs_bits;
132     
133     // number of bits in block offset
134     bo_bits = log2(cache_info.blocksize);
135     set_bits = log2(num_sets());
136     bs_bits = log2(c->mem_block_size);
137     
138     if (bs_bits<bo_bits || bs_bits >= (bo_bits+set_bits)) { 
139         c->actual_num_colors = 1;
140         c->color_mask=0;
141         c->color_shift=0;
142         c->min_color=0;
143         c->max_color=0;
144     } else {
145         c->actual_num_colors = pow2(bo_bits+set_bits-bs_bits);
146         c->color_mask = (c->actual_num_colors-1);
147         c->color_shift = bs_bits;
148         c->min_color = FLOOR_DIV(c->min_color,CEIL_DIV(c->expected_num_colors,c->actual_num_colors));
149         c->max_color = FLOOR_DIV(c->max_color,CEIL_DIV(c->expected_num_colors,c->actual_num_colors));
150     }
151 }
152
153 int v3_init_cachepart_vm(struct v3_vm_info *vm, struct v3_xml *config)
154 {
155     extern uint64_t v3_mem_block_size;
156     v3_cfg_tree_t *cp;
157     char *block_size_s;
158     char *num_colors_s;
159     char *min_color_s;
160     char *max_color_s;
161     uint64_t req_block_size, req_num_colors, req_min_color, req_max_color;
162     v3_cachepart_t *c = &(vm->cachepart_state);
163
164     if (getcacheinfo()) { 
165         PrintError(VM_NONE,VCORE_NONE,"cachepart: getcacheinfo failed!\n");
166         return -1;
167     }
168
169     if (!config || !(cp=v3_cfg_subtree(config,"cachepart"))) { 
170         PrintDebug(vm,VCORE_NONE,"cachepart: no cachepart configuration found\n");
171         return 0;
172     }
173     
174     if (!(block_size_s=v3_cfg_val(cp,"block_size"))) { 
175         PrintError(vm,VCORE_NONE,"cachepart: missing block_size parameter\n");
176         return 0;
177     }
178
179     req_block_size = atoi(block_size_s);
180
181     if (!(num_colors_s=v3_cfg_val(cp,"num_colors"))) { 
182         PrintError(vm,VCORE_NONE,"cachepart: missing num_colors parameter\n");
183         return -1;
184     }
185     
186     req_num_colors=atoi(num_colors_s);
187
188     if (!(min_color_s=v3_cfg_val(cp,"min_color"))) { 
189         PrintError(vm,VCORE_NONE,"cachepart: missing min_color parameter\n");
190         return -1;
191     }
192
193     req_min_color=atoi(min_color_s);
194
195     if (!(max_color_s=v3_cfg_val(cp,"max_color"))) { 
196         PrintError(vm,VCORE_NONE,"cachepart: missing max_color parameter\n");
197         return -1;
198     }
199     
200     req_max_color=atoi(max_color_s);
201         
202     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);
203
204     if (req_block_size!=v3_mem_block_size) { 
205         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);
206         return -1;
207     }
208
209     if (req_max_color>=req_num_colors || req_min_color>req_max_color) {
210         PrintError(vm,VCORE_NONE,"cachepart: min/max color request is nonsensical\n");
211         return -1;
212     }
213     
214     memset(c,0,sizeof(*c));
215
216     c->mem_block_size=req_block_size;
217     c->expected_num_colors=req_num_colors;
218     c->min_color=req_min_color;
219     c->max_color=req_max_color;
220
221     // Now update the color structure to reflect the cache constraints
222     build_colors(c);
223
224
225     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);
226
227     if (vm->resource_control.pg_filter_func || vm->resource_control.pg_filter_state) { 
228         PrintError(vm,VCORE_NONE, "cachepart: paging filter functions and state are already installed...\n");
229         return -1;
230     }
231     
232     vm->resource_control.pg_filter_func = (int (*)(void *,void*)) v3_cachepart_filter;
233     vm->resource_control.pg_filter_state = &vm->cachepart_state;
234
235
236     return 0;
237     
238 }
239
240 int v3_deinit_cachepart_vm(struct v3_vm_info *vm)
241 {
242     // nothing to do
243     return 0;
244 }
245
246 int v3_init_cachepart_core(struct guest_info *core)
247 {
248     // nothing to do yet
249     return 0;
250 }
251
252 int v3_deinit_cachepart_core(struct guest_info *core)
253 {
254     // nothing to do yet
255     return 0;
256 }
257
258
259 int v3_cachepart_filter(void *paddr, v3_cachepart_t *c)
260 {
261     uint64_t a = (uint64_t)paddr;
262     uint64_t color = (a >> c->color_shift) & c->color_mask;
263
264     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");
265
266     return color>=c->min_color && color<=c->max_color;
267
268 }
269