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 uint64_t log2(uint64_t x)
108 static uint64_t pow2(uint64_t n)
118 static uint64_t num_lines()
120 return FLOOR_DIV(cache_info.size,cache_info.blocksize);
123 static uint64_t num_sets()
125 return FLOOR_DIV(num_lines(),cache_info.associativity);
129 static void build_colors(v3_cachepart_t *c)
131 uint64_t bo_bits, set_bits, bs_bits;
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);
138 if (bs_bits<bo_bits || bs_bits >= (bo_bits+set_bits)) {
139 c->actual_num_colors = 1;
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));
153 int v3_init_cachepart_vm(struct v3_vm_info *vm, struct v3_xml *config)
155 extern uint64_t v3_mem_block_size;
161 uint64_t req_block_size, req_num_colors, req_min_color, req_max_color;
162 v3_cachepart_t *c = &(vm->cachepart_state);
164 if (getcacheinfo()) {
165 PrintError(VM_NONE,VCORE_NONE,"cachepart: getcacheinfo failed!\n");
169 if (!config || !(cp=v3_cfg_subtree(config,"cachepart"))) {
170 PrintDebug(vm,VCORE_NONE,"cachepart: no cachepart configuration found\n");
174 if (!(block_size_s=v3_cfg_val(cp,"block_size"))) {
175 PrintError(vm,VCORE_NONE,"cachepart: missing block_size parameter\n");
179 req_block_size = atoi(block_size_s);
181 if (!(num_colors_s=v3_cfg_val(cp,"num_colors"))) {
182 PrintError(vm,VCORE_NONE,"cachepart: missing num_colors parameter\n");
186 req_num_colors=atoi(num_colors_s);
188 if (!(min_color_s=v3_cfg_val(cp,"min_color"))) {
189 PrintError(vm,VCORE_NONE,"cachepart: missing min_color parameter\n");
193 req_min_color=atoi(min_color_s);
195 if (!(max_color_s=v3_cfg_val(cp,"max_color"))) {
196 PrintError(vm,VCORE_NONE,"cachepart: missing max_color parameter\n");
200 req_max_color=atoi(max_color_s);
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);
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);
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");
214 memset(c,0,sizeof(*c));
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;
221 // Now update the color structure to reflect the cache constraints
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);
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");
232 vm->resource_control.pg_filter_func = (int (*)(void *,void*)) v3_cachepart_filter;
233 vm->resource_control.pg_filter_state = &vm->cachepart_state;
240 int v3_deinit_cachepart_vm(struct v3_vm_info *vm)
246 int v3_init_cachepart_core(struct guest_info *core)
252 int v3_deinit_cachepart_core(struct guest_info *core)
259 int v3_cachepart_filter(void *paddr, v3_cachepart_t *c)
261 uint64_t a = (uint64_t)paddr;
262 uint64_t color = (a >> c->color_shift) & c->color_mask;
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");
266 return color>=c->min_color && color<=c->max_color;