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.
6 * The V3VEE Project is a joint project between Northwestern University
7 * and the University of New Mexico. You can find out more at
10 * Copyright (c) 2015, The V3VEE Project <http://www.v3vee.org>
11 * All rights reserved.
13 * Author: Peter Dinda <pdinda@northwestern.edu>
15 * This is free software. You are permitted to use,
16 * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
19 #include <palacios/vmm.h>
20 #include <palacios/vm_guest.h>
21 #include <interfaces/vmm_cache_info.h>
23 #ifndef V3_CONFIG_DEBUG_CACHEPART
25 #define PrintDebug(fmt, args...)
34 max_color=MAX_COLOR />
36 Cache partitioning support
38 We are partioning the last level shared cache here.
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
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
50 = the range of allowed page colors allowed for this VM
51 with respect to the range [0,NUMCOLORS)
55 static struct v3_cache_info cache_info;
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)))
62 static inline int getcacheinfo()
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");
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);
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");
83 int v3_init_cachepart()
85 PrintDebug(VM_NONE,VCORE_NONE,"cachepart: init\n");
89 int v3_deinit_cachepart()
91 PrintDebug(VM_NONE,VCORE_NONE,"cachepart: deinit\n");
96 static int bitcount(uint64_t x)
107 static int is_pow2(x)
115 static uint64_t log2(uint64_t x)
127 static uint64_t pow2(uint64_t n)
137 static uint64_t num_lines()
139 return FLOOR_DIV(cache_info.size,cache_info.blocksize);
142 static uint64_t num_sets()
144 return FLOOR_DIV(num_lines(),cache_info.associativity);
148 static void build_colors(v3_cachepart_t *c)
150 uint64_t bo_bits, set_bits, bs_bits;
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);
157 if (bs_bits<bo_bits || bs_bits >= (bo_bits+set_bits)) {
158 c->actual_num_colors = 1;
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));
172 int v3_init_cachepart_vm(struct v3_vm_info *vm, struct v3_xml *config)
174 extern uint64_t v3_mem_block_size;
180 uint64_t req_block_size, req_num_colors, req_min_color, req_max_color;
181 v3_cachepart_t *c = &(vm->cachepart_state);
183 if (getcacheinfo()) {
184 PrintError(VM_NONE,VCORE_NONE,"cachepart: getcacheinfo failed!\n");
188 if (!config || !(cp=v3_cfg_subtree(config,"cachepart"))) {
189 PrintDebug(vm,VCORE_NONE,"cachepart: no cachepart configuration found\n");
193 if (!(block_size_s=v3_cfg_val(cp,"block_size"))) {
194 PrintError(vm,VCORE_NONE,"cachepart: missing block_size parameter\n");
198 req_block_size = atoi(block_size_s);
200 if (!(num_colors_s=v3_cfg_val(cp,"num_colors"))) {
201 PrintError(vm,VCORE_NONE,"cachepart: missing num_colors parameter\n");
205 req_num_colors=atoi(num_colors_s);
207 if (!(min_color_s=v3_cfg_val(cp,"min_color"))) {
208 PrintError(vm,VCORE_NONE,"cachepart: missing min_color parameter\n");
212 req_min_color=atoi(min_color_s);
214 if (!(max_color_s=v3_cfg_val(cp,"max_color"))) {
215 PrintError(vm,VCORE_NONE,"cachepart: missing max_color parameter\n");
219 req_max_color=atoi(max_color_s);
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);
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);
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");
233 memset(c,0,sizeof(*c));
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;
240 // Now update the color structure to reflect the cache constraints
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);
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");
251 vm->resource_control.pg_filter_func = (int (*)(void *,void*)) v3_cachepart_filter;
252 vm->resource_control.pg_filter_state = &vm->cachepart_state;
255 // V3_Sleep(50000000);
261 int v3_deinit_cachepart_vm(struct v3_vm_info *vm)
267 int v3_init_cachepart_core(struct guest_info *core)
273 int v3_deinit_cachepart_core(struct guest_info *core)
279 static unsigned count=0;
281 int v3_cachepart_filter(void *paddr, v3_cachepart_t *c)
283 uint64_t a = (uint64_t)paddr;
284 uint64_t color = (a >> c->color_shift) & c->color_mask;
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");
295 return color>=c->min_color && color<=c->max_color;