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();
36 static struct vm_cpu_mapper_impl *cpu_mapper = NULL;
38 static uint_t cpu_mapper_hash_fn(addr_t key) {
39 char * name = (char *)key;
40 return v3_hash_buffer((uint8_t *)name, strlen(name));
43 static int cpu_mapper_eq_fn(addr_t key1, addr_t key2) {
44 char * name1 = (char *)key1;
45 char * name2 = (char *)key2;
47 return (strcmp(name1, name2) == 0);
50 int V3_init_cpu_mapper() {
52 PrintDebug(VM_NONE, VCORE_NONE,"Initializing cpu_mapper");
54 master_cpu_mapper_table = v3_create_htable(0, cpu_mapper_hash_fn, cpu_mapper_eq_fn);
55 return create_default_cpu_mapper();
59 int v3_register_cpu_mapper(struct vm_cpu_mapper_impl *s) {
61 PrintDebug(VM_NONE, VCORE_NONE,"Registering cpu_mapper (%s)\n", s->name);
63 if (v3_htable_search(master_cpu_mapper_table, (addr_t)(s->name))) {
64 PrintError(VM_NONE, VCORE_NONE, "Multiple instances of cpu_mapper (%s)\n", s->name);
68 if (v3_htable_insert(master_cpu_mapper_table,
71 PrintError(VM_NONE, VCORE_NONE, "Could not register cpu_mapper (%s)\n", s->name);
78 struct vm_cpu_mapper_impl *v3_cpu_mapper_lookup(char *name)
80 return (struct vm_cpu_mapper_impl *)v3_htable_search(master_cpu_mapper_table, (addr_t)(name));
83 int V3_enable_cpu_mapper() {
87 mapper_name = v3_lookup_option("cpu_mapper");
90 cpu_mapper = v3_cpu_mapper_lookup(mapper_name);
94 cpu_mapper = v3_cpu_mapper_lookup(default_strategy);
98 PrintError(VM_NONE, VCORE_NONE,"Specified Palacios cpu_mapper \"%s\" not found.\n", default_strategy);
102 PrintDebug(VM_NONE, VCORE_NONE,"cpu_mapper %s found",cpu_mapper->name);
104 if (cpu_mapper->init) {
105 return cpu_mapper->init();
111 int v3_cpu_mapper_register_vm(struct v3_vm_info *vm,unsigned int cpu_mask) {
112 if (cpu_mapper->vm_init) {
113 return cpu_mapper->vm_init(vm,cpu_mask);
119 int v3_cpu_mapper_admit_vm(struct v3_vm_info *vm) {
120 if (cpu_mapper->admit) {
121 return cpu_mapper->admit(vm);
128 int v3_cpu_mapper_admit_core(struct v3_vm_info * vm, int vcore_id, int target_cpu) {
129 if (cpu_mapper->admit_core) {
130 return cpu_mapper->admit_core(vm,vcore_id,target_cpu);
138 int default_mapper_vm_init(struct v3_vm_info *vm, unsigned int cpu_mask)
141 PrintDebug(vm, VCORE_NONE,"mapper. default_mapper_init\n");
145 uint8_t * core_mask = (uint8_t *)&cpu_mask;
147 for (i = 0, vcore_id = vm->num_cores - 1; vcore_id >= 0; i++) {
151 struct guest_info * core = &(vm->cores[vcore_id]);
152 char * specified_cpu = v3_cfg_val(core->core_cfg_data, "target_cpu");
153 uint32_t core_idx = 0;
155 if (specified_cpu != NULL) {
156 core_idx = atoi(specified_cpu);
159 PrintError(vm, VCORE_NONE, "Target CPU out of bounds (%d) \n", core_idx);
162 i--; // We reset the logical core idx. Not strictly necessary I guess...
167 major = core_idx / 8;
168 minor = core_idx % 8;
170 if ((core_mask[major] & (0x1 << minor)) == 0) {
171 PrintError(vm, VCORE_NONE, "Logical CPU %d not available for virtual core %d; not started\n",
174 if (specified_cpu != NULL) {
175 PrintError(vm, VCORE_NONE, "CPU was specified explicitly (%d). HARD ERROR\n", core_idx);
184 core->pcpu_id = core_idx;
197 int default_mapper_admit_core(struct v3_vm_info * vm, int vcore_id, int target_cpu){
202 int default_mapper_admit(struct v3_vm_info *vm){
207 static struct vm_cpu_mapper_impl default_mapper_impl = {
211 .vm_init = default_mapper_vm_init,
213 .admit_core = default_mapper_admit_core,
214 .admit = default_mapper_admit
218 static int create_default_cpu_mapper()
220 v3_register_cpu_mapper(&default_mapper_impl);