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) 2013, Oscar Mondragon <omondrag@cs.unm.edu>
11 * Copyright (c) 2013, Patrick G. Bridges <bridges@cs.unm.edu>
12 * Copyright (c) 2013, The V3VEE Project <http://www.v3vee.org>
13 * All rights reserved.
15 * Author: Oscar Mondragon <omondrag@cs.unm.edu>
16 * Patrick G. Bridges <bridges@cs.unm.edu>
18 * This is free software. You are permitted to use,
19 * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
22 #include <palacios/vmm.h>
23 #include <palacios/vm_guest.h>
24 #include <palacios/vmm_cpu_mapper.h>
25 #include <palacios/vmm_hashtable.h>
27 #ifndef V3_CONFIG_DEBUG_CPU_MAPPER
29 #define PrintDebug(fmt, args...)
32 static char default_strategy[] = "default";
33 static struct hashtable * master_cpu_mapper_table = NULL;
34 static int create_default_cpu_mapper();
35 static int destroy_default_cpu_mapper();
37 static struct vm_cpu_mapper_impl *cpu_mapper = NULL;
39 static uint_t cpu_mapper_hash_fn(addr_t key) {
40 char * name = (char *)key;
41 return v3_hash_buffer((uint8_t *)name, strlen(name));
44 static int cpu_mapper_eq_fn(addr_t key1, addr_t key2) {
45 char * name1 = (char *)key1;
46 char * name2 = (char *)key2;
48 return (strcmp(name1, name2) == 0);
51 int V3_init_cpu_mapper() {
53 PrintDebug(VM_NONE, VCORE_NONE,"Initializing cpu_mapper");
55 master_cpu_mapper_table = v3_create_htable(0, cpu_mapper_hash_fn, cpu_mapper_eq_fn);
56 return create_default_cpu_mapper();
60 int V3_deinit_cpu_mapper() {
62 destroy_default_cpu_mapper();
63 v3_free_htable(master_cpu_mapper_table, 1, 1);
67 int v3_register_cpu_mapper(struct vm_cpu_mapper_impl *s) {
69 PrintDebug(VM_NONE, VCORE_NONE,"Registering cpu_mapper (%s)\n", s->name);
71 if (v3_htable_search(master_cpu_mapper_table, (addr_t)(s->name))) {
72 PrintError(VM_NONE, VCORE_NONE, "Multiple instances of cpu_mapper (%s)\n", s->name);
76 if (v3_htable_insert(master_cpu_mapper_table,
79 PrintError(VM_NONE, VCORE_NONE, "Could not register cpu_mapper (%s)\n", s->name);
86 struct vm_cpu_mapper_impl *v3_unregister_cpu_mapper(char *name) {
88 PrintDebug(VM_NONE, VCORE_NONE,"Unregistering cpu_mapper (%s)\n",name);
90 struct vm_cpu_mapper_impl *f = (struct vm_cpu_mapper_impl *) v3_htable_remove(master_cpu_mapper_table,(addr_t)(name),0);
93 PrintError(VM_NONE,VCORE_NONE,"Could not find cpu_mapper (%s)\n",name);
101 struct vm_cpu_mapper_impl *v3_cpu_mapper_lookup(char *name)
103 return (struct vm_cpu_mapper_impl *)v3_htable_search(master_cpu_mapper_table, (addr_t)(name));
106 int V3_enable_cpu_mapper() {
110 mapper_name = v3_lookup_option("cpu_mapper");
113 cpu_mapper = v3_cpu_mapper_lookup(mapper_name);
117 cpu_mapper = v3_cpu_mapper_lookup(default_strategy);
121 PrintError(VM_NONE, VCORE_NONE,"Specified Palacios cpu_mapper \"%s\" not found.\n", default_strategy);
125 PrintDebug(VM_NONE, VCORE_NONE,"cpu_mapper %s found",cpu_mapper->name);
127 if (cpu_mapper->init) {
128 return cpu_mapper->init();
134 int V3_disable_cpu_mapper()
136 if (cpu_mapper->deinit) {
137 return cpu_mapper->deinit();
143 int v3_cpu_mapper_register_vm(struct v3_vm_info *vm,unsigned int cpu_mask) {
144 if (cpu_mapper->vm_init) {
145 return cpu_mapper->vm_init(vm,cpu_mask);
151 int v3_cpu_mapper_admit_vm(struct v3_vm_info *vm) {
152 if (cpu_mapper->admit) {
153 return cpu_mapper->admit(vm);
160 int v3_cpu_mapper_admit_core(struct v3_vm_info * vm, int vcore_id, int target_cpu) {
161 if (cpu_mapper->admit_core) {
162 return cpu_mapper->admit_core(vm,vcore_id,target_cpu);
170 int default_mapper_vm_init(struct v3_vm_info *vm, unsigned int cpu_mask)
173 PrintDebug(vm, VCORE_NONE,"mapper. default_mapper_init\n");
177 uint8_t * core_mask = (uint8_t *)&cpu_mask;
179 for (i = 0, vcore_id = vm->num_cores - 1; vcore_id >= 0; i++) {
183 struct guest_info * core = &(vm->cores[vcore_id]);
184 char * specified_cpu = v3_cfg_val(core->core_cfg_data, "target_cpu");
185 uint32_t core_idx = 0;
187 if (specified_cpu != NULL) {
188 core_idx = atoi(specified_cpu);
191 PrintError(vm, VCORE_NONE, "Target CPU out of bounds (%d) \n", core_idx);
194 i--; // We reset the logical core idx. Not strictly necessary I guess...
199 major = core_idx / 8;
200 minor = core_idx % 8;
202 if ((core_mask[major] & (0x1 << minor)) == 0) {
203 PrintError(vm, VCORE_NONE, "Logical CPU %d not available for virtual core %d; not started\n",
206 if (specified_cpu != NULL) {
207 PrintError(vm, VCORE_NONE, "CPU was specified explicitly (%d). HARD ERROR\n", core_idx);
216 core->pcpu_id = core_idx;
229 int default_mapper_admit_core(struct v3_vm_info * vm, int vcore_id, int target_cpu){
234 int default_mapper_admit(struct v3_vm_info *vm){
239 static struct vm_cpu_mapper_impl default_mapper_impl = {
243 .vm_init = default_mapper_vm_init,
245 .admit_core = default_mapper_admit_core,
246 .admit = default_mapper_admit
250 static int create_default_cpu_mapper()
252 v3_register_cpu_mapper(&default_mapper_impl);
256 static int destroy_default_cpu_mapper()
258 v3_unregister_cpu_mapper(default_mapper_impl.name);