allow_devmem.o \
util-queue.o \
util-hashtable.o \
- linux-exts.o
+ linux-exts.o \
+ buddy.o \
+ numa.o
v3vee-$(V3_CONFIG_CONSOLE) += iface-console.o
v3vee-$(V3_CONFIG_FILE) += iface-file.o
return -1;
}
- mp = kmalloc_node(sizeof(struct buddy_mempool), GFP_KERNEL, zone->node_id);
+ mp = palacios_alloc_node_extended(sizeof(struct buddy_mempool), GFP_KERNEL, zone->node_id);
if (IS_ERR(mp)) {
ERROR("Could not allocate mempool\n");
/* Allocate a bitmap with 1 bit per minimum-sized block */
mp->num_blocks = (1UL << pool_order) / (1UL << zone->min_order);
- mp->tag_bits = kmalloc_node(
+ mp->tag_bits = palacios_alloc_node_extended(
BITS_TO_LONGS(mp->num_blocks) * sizeof(long), GFP_KERNEL, zone->node_id
);
/* Initially mark all minimum-sized blocks as allocated */
bitmap_zero(mp->tag_bits, mp->num_blocks);
- spin_lock_irqsave(&(zone->lock), flags);
+ palacios_spinlock_lock_irqsave(&(zone->lock), flags);
ret = insert_mempool(zone, mp);
- spin_unlock_irqrestore(&(zone->lock), flags);
+ palacios_spinlock_unlock_irqrestore(&(zone->lock), flags);
if (ret == -1) {
ERROR("Error: Could not insert mempool into zone\n");
- kfree(mp->tag_bits);
- kfree(mp);
+ palacios_free(mp->tag_bits);
+ palacios_free(mp);
return -1;
}
buddy_free(zone, base_addr, pool_order);
- printk("Added memory pool (addr=%p), order=%lu\n", (void *)base_addr, pool_order);
+ INFO("Added memory pool (addr=%p), order=%lu\n", (void *)base_addr, pool_order);
return 0;
}
list_del(&(block->link));
rb_erase(&(pool->tree_node), &(zone->mempools));
- kfree(pool->tag_bits);
- kfree(pool);
+ palacios_free(pool->tag_bits);
+ palacios_free(pool);
zone->num_pools--;
unsigned long flags = 0;
int ret = 0;
- spin_lock_irqsave(&(zone->lock), flags);
+ palacios_spinlock_lock_irqsave(&(zone->lock), flags);
ret = __buddy_remove_mempool(zone, base_addr, force);
- spin_unlock_irqrestore(&(zone->lock), flags);
+ palacios_spinlock_unlock_irqrestore(&(zone->lock), flags);
return ret;
}
order = zone->min_order;
}
- printk("zone=%p, order=%lu\n", zone, order);
+ INFO("zone=%p, order=%lu\n", zone, order);
- spin_lock_irqsave(&(zone->lock), flags);
+ palacios_spinlock_lock_irqsave(&(zone->lock), flags);
for (j = order; j <= zone->max_order; j++) {
- printk("Order iter=%lu\n", j);
+ INFO("Order iter=%lu\n", j);
/* Try to allocate the first block in the order j list */
list = &zone->avail[j];
mark_allocated(mp, block);
- printk("pool=%p, block=%p, order=%lu, j=%lu\n", mp, block, order, j);
+ INFO("pool=%p, block=%p, order=%lu, j=%lu\n", mp, block, order, j);
/*
- spin_unlock_irqrestore(&(zone->lock), flags);
+ palacios_spinlock_unlock_irqrestore(&(zone->lock), flags);
return 0;
*/
mp->num_free_blocks -= (1UL << (order - zone->min_order));
- spin_unlock_irqrestore(&(zone->lock), flags);
+ palacios_spinlock_unlock_irqrestore(&(zone->lock), flags);
return __pa(block);
}
- spin_unlock_irqrestore(&(zone->lock), flags);
+ palacios_spinlock_unlock_irqrestore(&(zone->lock), flags);
return (uintptr_t)NULL;
}
}
- spin_lock_irqsave(&(zone->lock), flags);
+ palacios_spinlock_lock_irqsave(&(zone->lock), flags);
pool = find_mempool(zone, addr);
if ((pool == NULL) || (order > pool->pool_order)) {
WARNING("Attempted to free an invalid page address (%p)\n", (void *)addr);
- spin_unlock_irqrestore(&(zone->lock), flags);
+ palacios_spinlock_unlock_irqrestore(&(zone->lock), flags);
return;
}
block = (struct block *) __va(addr);
if (is_available(pool, block)) {
- printk(KERN_ERR "Error: Freeing an available block\n");
- spin_unlock_irqrestore(&(zone->lock), flags);
+ ERROR("Error: Freeing an available block\n");
+ palacios_spinlock_unlock_irqrestore(&(zone->lock), flags);
return;
}
mark_available(pool, block);
list_add(&(block->link), &(zone->avail[order]));
- spin_unlock_irqrestore(&(zone->lock), flags);
+ palacios_spinlock_unlock_irqrestore(&(zone->lock), flags);
}
seq_printf(s, " Zone Max Order=%lu, Min Order=%lu\n",
zone->max_order, zone->min_order);
- spin_lock_irqsave(&(zone->lock), flags);
+ palacios_spinlock_lock_irqsave(&(zone->lock), flags);
for (i = zone->min_order; i <= zone->max_order; i++) {
}
}
- spin_unlock_irqrestore(&(zone->lock), flags);
+ palacios_spinlock_unlock_irqrestore(&(zone->lock), flags);
return 0;
}
static int zone_proc_open(struct inode * inode, struct file * filp) {
struct proc_dir_entry * proc_entry = PDE(inode);
- printk("proc_entry at %p, data at %p\n", proc_entry, proc_entry->data);
+ INFO("proc_entry at %p, data at %p\n", proc_entry, proc_entry->data);
return single_open(filp, zone_mem_show, proc_entry->data);
}
};
+extern struct proc_dir_entry * palacios_proc_dir;
void buddy_deinit(struct buddy_memzone * zone) {
unsigned long flags;
- spin_lock_irqsave(&(zone->lock), flags);
+ palacios_spinlock_lock_irqsave(&(zone->lock), flags);
// for each pool, free it
+#warning We really need to free the memory pools here
- spin_unlock_irqrestore(&(zone->lock), flags);
+ palacios_spinlock_unlock_irqrestore(&(zone->lock), flags);
{
char proc_file_name[128];
}
- kfree(zone->avail);
- kfree(zone);
+ palacios_free(zone->avail);
+ palacios_free(zone);
return;
}
if (min_order > max_order)
return NULL;
- zone = kmalloc_node(sizeof(struct buddy_memzone), GFP_KERNEL, node_id);
+ zone = palacios_alloc_node_extended(sizeof(struct buddy_memzone), GFP_KERNEL, node_id);
- printk("Allocated zone at %p\n", zone);
+ INFO("Allocated zone at %p\n", zone);
if (IS_ERR(zone)) {
ERROR("Could not allocate memzone\n");
zone->node_id = node_id;
/* Allocate a list for every order up to the maximum allowed order */
- zone->avail = kmalloc_node((max_order + 1) * sizeof(struct list_head), GFP_KERNEL, zone->node_id);
+ zone->avail = palacios_alloc_node_extended((max_order + 1) * sizeof(struct list_head), GFP_KERNEL, zone->node_id);
- printk("Allocated free lists at %p\n", zone->avail);
+ INFO("Allocated free lists at %p\n", zone->avail);
/* Initially all lists are empty */
for (i = 0; i <= max_order; i++) {
}
- spin_lock_init(&(zone->lock));
+ palacios_spinlock_init(&(zone->lock));
zone->mempools.rb_node = NULL;
- printk("Allocated zone at %p\n", zone);
+ INFO("Allocated zone at %p\n", zone);
{
struct proc_dir_entry * zone_entry = NULL;
zone_entry->proc_fops = &zone_proc_ops;
zone_entry->data = zone;
} else {
- printk(KERN_ERR "Error creating memory zone proc file\n");
+ ERROR("Error creating memory zone proc file\n");
}
}
static int v3_major_num = 0;
static struct v3_guest * guest_map[MAX_VMS] = {[0 ... MAX_VMS - 1] = 0};
-static struct proc_dir_entry *dir = 0;
+struct proc_dir_entry * palacios_proc_dir = NULL;
struct class * v3_class = NULL;
static struct cdev ctrl_dev;
struct proc_dir_entry *palacios_get_procdir(void)
{
- return dir;
+ return palacios_proc_dir;
}
return len;
}
-static int show_mem(char * buf, char ** start, off_t off, int count,
- int * eof, void * data)
-{
- int len = 0;
-
- len = snprintf(buf,count, "%p\n", (void *)get_palacios_base_addr());
- len += snprintf(buf+len,count-len, "%lld\n", get_palacios_num_pages());
-
- return len;
-}
-
goto failure1;
}
- dir = proc_mkdir("v3vee", NULL);
- if(dir) {
+ palacios_proc_dir = proc_mkdir("v3vee", NULL);
+ if (palacios_proc_dir) {
struct proc_dir_entry *entry;
- entry = create_proc_read_entry("v3-guests", 0444, dir,
+ entry = create_proc_read_entry("v3-guests", 0444, palacios_proc_dir,
read_guests, NULL);
if (entry) {
INFO("/proc/v3vee/v3-guests successfully created\n");
goto failure1;
}
- entry = create_proc_read_entry("v3-mem", 0444, dir,
- show_mem, NULL);
- if (entry) {
- INFO("/proc/v3vee/v3-mem successfully added\n");
- } else {
- ERROR("Could not create proc entry\n");
- goto failure1;
- }
} else {
ERROR("Could not create proc entry\n");
goto failure1;
palacios_deinit_mm();
- remove_proc_entry("v3-guests", dir);
- remove_proc_entry("v3-mem", dir);
+ remove_proc_entry("v3-guests", palacios_proc_dir);
remove_proc_entry("v3vee", NULL);
DEBUG("Palacios Module Mallocs = %d, Frees = %d\n", mod_allocs, mod_frees);
#include <linux/mm.h>
-#include "palacios.h"
#include <interfaces/vmm_numa.h>
+#include "palacios.h"
+
+
#if 0
/* Read in the CPU to Node mapping */
{
- topology.cpu_to_node_map = kmalloc(GFP_KERNEL,
- sizeof(u32) *
- topology.num_cpus);
+ topology.cpu_to_node_map = palacios_alloc(sizeof(u32) * topology.num_cpus);
if (IS_ERR(topology.cpu_to_node_map)) {
ERROR("Could not allocate cpu to node map\n");
if (copy_from_user(topology.cpu_to_node_map, argp,
sizeof(u32) * topology.num_cpus)) {
ERROR("Could not copy cpu to node map from user space\n");
- kfree(topology.cpu_to_node_map);
+ palacios_free(topology.cpu_to_node_map);
return -1;
}
{
int i = 0;
- topology.mem_to_node_map = kmalloc(GFP_KERNEL,
- sizeof(struct mem_region) *
- topology.num_mem_regions);
+ topology.mem_to_node_map = palacios_alloc(sizeof(struct mem_region) * topology.num_mem_regions);
if (IS_ERR(topology.mem_to_node_map)) {
ERROR("Could not allocate mem to node map\n");
- kfree(topology.cpu_to_node_map);
+ palacios_free(topology.cpu_to_node_map);
return -1;
}
if (copy_from_user(topology.mem_to_node_map, argp,
sizeof(struct mem_region) * topology.num_mem_regions)) {
ERROR("Coudl not copy mem to node map from user space\n");
- kfree(topology.cpu_to_node_map);
- kfree(topology.mem_to_node_map);
+ palacios_free(topology.cpu_to_node_map);
+ palacios_free(topology.mem_to_node_map);
return -1;
}
/* Read in the distance table */
{
- topology.distance_table = kmalloc(GFP_KERNEL,
- sizeof(u32) *
- (topology.num_nodes * topology.num_nodes));
+ topology.distance_table = palacios_alloc(sizeof(u32) * (topology.num_nodes * topology.num_nodes));
if (IS_ERR(topology.distance_table)) {
ERROR("Could not allocate distance table\n");
- kfree(topology.cpu_to_node_map);
- kfree(topology.mem_to_node_map);
+ palacios_free(topology.cpu_to_node_map);
+ palacios_free(topology.mem_to_node_map);
return -1;
}
if (copy_from_user(topology.distance_table, argp,
sizeof(u32) * (topology.num_nodes * topology.num_nodes))) {
ERROR("Could not copy distance table from user space\n");
- kfree(topology.cpu_to_node_map);
- kfree(topology.mem_to_node_map);
- kfree(topology.distance_table);
+ palacios_free(topology.cpu_to_node_map);
+ palacios_free(topology.mem_to_node_map);
+ palacios_free(topology.distance_table);
return -1;
}
int i = 0;
int j = 0;
- printk("Created NUMA topology from user space\n");
- printk("Number of Nodes: %d, CPUs: %d, MEM regions: %d\n",
+ INFO("Created NUMA topology from user space\n");
+ INFO("Number of Nodes: %d, CPUs: %d, MEM regions: %d\n",
topology.num_nodes, topology.num_cpus, topology.num_mem_regions);
- printk("CPU mapping\n");
+ INFO("CPU mapping\n");
for (i = 0; i < topology.num_cpus; i++) {
- printk("\tCPU %d -> Node %d\n", i, topology.cpu_to_node_map[i]);
+ INFO("\tCPU %d -> Node %d\n", i, topology.cpu_to_node_map[i]);
}
- printk("Memory mapping\n");
+ INFO("Memory mapping\n");
for (i = 0; i < topology.num_mem_regions; i++) {
struct mem_region * region = &(topology.mem_to_node_map[i]);
- printk("\tMEM %p - %p -> Node %d\n",
+ INFO("\tMEM %p - %p -> Node %d\n",
region->start_addr,
region->end_addr,
region->node_id);
}
- printk("Distance Table\n");
+ INFO("Distance Table\n");
for (i = 0; i < topology.num_nodes; i++) {
- printk("\t%d", i);
+ INFO("\t%d", i);
}
- printk("\n");
+ INFO("\n");
for (i = 0; i < topology.num_nodes; i++) {
- printk("%d", i);
+ INFO("%d", i);
for (j = 0; j < topology.num_nodes; j++) {
- printk("\t%d", topology.distance_table[j + (i * topology.num_nodes)]);
+ INFO("\t%d", topology.distance_table[j + (i * topology.num_nodes)]);
}
- printk("\n");
+ INFO("\n");
}
void palacios_free_pages(void *page_addr, int num_pages);
void *palacios_alloc(unsigned int size);
void *palacios_alloc_extended(unsigned int size, unsigned int flags);
+// FIX
+// NEED A palacios_alloc_node wrapper
+//
+#define palacios_alloc_node_extended(size, flags, node) kmalloc_node(size,flags,node)
void palacios_free(void *);
void *palacios_valloc(unsigned int size); // use instead of vmalloc
void palacios_vfree(void *); // use instead of vfree
#include <palacios/vmm_exits.h>
#include <palacios/vmm_events.h>
#include <palacios/vmm_scheduler.h>
+#include <palacios/vmm_fw_cfg.h>
#include <palacios/vmm_perftune.h>
char name[128];
v3_vm_class_t vm_class;
+ struct v3_fw_cfg_state fw_cfg_state;
addr_t mem_size; /* In bytes for now */
uint32_t mem_align;
return 0;
}
+static struct v3_segment * get_instr_segment(struct guest_info * core, struct x86_instr * instr) {
+ struct v3_segment * seg = &(core->segments.ds);
+
+ if (instr->prefixes.cs_override) {
+ seg = &(core->segments.cs);
+ } else if (instr->prefixes.es_override) {
+ seg = &(core->segments.es);
+ } else if (instr->prefixes.ss_override) {
+ seg = &(core->segments.ss);
+ } else if (instr->prefixes.fs_override) {
+ seg = &(core->segments.fs);
+ } else if (instr->prefixes.gs_override) {
+ seg = &(core->segments.gs);
+ }
+
+ return seg;
+}
+
#define ADDR_MASK(val, length) ({ \
obj-$(V3_CONFIG_HOST_PWRSTAT) += vmm_pwrstat.o
obj-y += null.o
-
+obj-y += vmm_numa.o
void V3_Init_NUMA(struct v3_numa_hooks * hooks) {
numa_hooks = hooks;
- V3_Print("V3 NUMA interface initialized\n");
+ V3_Print(VM_NONE, VCORE_NONE, "V3 NUMA interface initialized\n");
return;
}
}
if (v3_gpa_to_hpa(&(vm->cores[0]), gpa, &hpa) == -1) {
- PrintError("Tried to find NUMA node for invalid GPA (%p)\n", (void *)gpa);
+ PrintError(vm, VCORE_NONE, "Tried to find NUMA node for invalid GPA (%p)\n", (void *)gpa);
return -1;
}
vmm_exits.o \
vmm_events.o \
vmm_perftune.o \
+ vmm_fw_cfg.o
obj-$(V3_CONFIG_XED) += vmm_xed.o
}
+
+ // Initialize fw_cfg state for VMM<->VM SEABIOS communication
+ if (v3_fw_cfg_init(vm) == -1) {
+ PrintError(vm, VCORE_NONE, "Error initializing Firmware Config (fw_cfg) state\n");
+ return -1;
+ }
+
/*
* Initialize configured devices
*/
static int post_config_pc(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
#define VGABIOS_START 0x000c0000
-#define ROMBIOS_START 0x000f0000
+#define ROMBIOS_START 0x000e0000
/* layout vgabios */
{
}
memcpy(rombios_dst, v3_rombios_start, v3_rombios_end - v3_rombios_start);
+
+ // SEABIOS gets mapped into end of 4GB region
+ if (v3_add_shadow_mem(vm, V3_MEM_CORE_ANY,
+ 0xfffe0000, 0xffffffff,
+ (addr_t)V3_PAddr(rombios_dst)) == -1) {
+ PrintError(vm, VCORE_NONE, "Error mapping SEABIOS to end of memory\n");
+ return -1;
+ }
+
}
}
static int fw_cfg_ctl_write(struct guest_info * core, uint16_t port, void * src, uint_t length, void * priv_data) {
- V3_ASSERT(length == 2);
+ V3_ASSERT(core->vm_info, core, length == 2);
struct v3_fw_cfg_state * cfg_state = (struct v3_fw_cfg_state *)priv_data;
uint16_t key = *(uint16_t *)src;
static int fw_cfg_data_read(struct guest_info * core, uint16_t port, void * src, uint_t length, void * priv_data) {
- V3_ASSERT(length == 1);
+ V3_ASSERT(core->vm_info, core, length == 1);
struct v3_fw_cfg_state * cfg_state = (struct v3_fw_cfg_state *)priv_data;
int arch = !!(cfg_state->cur_entry & FW_CFG_ARCH_LOCAL);
}
static int fw_cfg_data_write(struct guest_info * core, uint16_t port, void * src, uint_t length, void * priv_data) {
- V3_ASSERT(length == 1);
+ V3_ASSERT(core->vm_info, core, length == 1);
struct v3_fw_cfg_state * cfg_state = (struct v3_fw_cfg_state *)priv_data;
int arch = !!(cfg_state->cur_entry & FW_CFG_ARCH_LOCAL);
int i = 0;
if (vm->mem_map.e820_count > E820_MAX_COUNT) {
- PrintError("Too much E820 table entries! (max is %d)\n", E820_MAX_COUNT);
+ PrintError(vm, VCORE_NONE,"Too much E820 table entries! (max is %d)\n", E820_MAX_COUNT);
return NULL;
}
e820 = V3_Malloc(sizeof(struct e820_table));
if (e820 == NULL) {
- PrintError("Out of memory!\n");
+ PrintError(vm, VCORE_NONE, "Out of memory!\n");
return NULL;
}
struct e820_table * e820 = e820_populate(vm);
if (e820 == NULL) {
- PrintError("Failed to populate E820 for FW interface!\n");
+ PrintError(vm, VCORE_NONE, "Failed to populate E820 for FW interface!\n");
return -1;
}
if (ret != 0) {
// V3_Free(e820);
- PrintError("Failed to hook FW CFG ports!\n");
+ PrintError(vm, VCORE_NONE, "Failed to hook FW CFG ports!\n");
return -1;
}
numa_fw_cfg = V3_Malloc((1 + vm->num_cores + num_nodes) * sizeof(uint64_t));
if (numa_fw_cfg == NULL) {
- PrintError("Could not allocate fw_cfg NUMA config space\n");
+ PrintError(vm, VCORE_NONE, "Could not allocate fw_cfg NUMA config space\n");
return -1;
}
int vnode_id = 0;
if ((!start_addr_str) || (!end_addr_str) || (!vnode_id_str)) {
- PrintError("Invalid memory layout in configuration\n");
+ PrintError(vm, VCORE_NONE, "Invalid memory layout in configuration\n");
V3_Free(numa_fw_cfg);
return -1;
}
{
uint64_t region_start = 0;
- V3_Print("NUMA CONFIG: (nodes=%llu)\n", numa_fw_cfg[0]);
+ V3_Print(vm, VCORE_NONE, "NUMA CONFIG: (nodes=%llu)\n", numa_fw_cfg[0]);
for (i = 0; i < vm->num_cores; i++) {
- V3_Print("\tCore %d -> Node %llu\n", i, numa_fw_cfg[core_offset + i]);
+ V3_Print(vm, VCORE_NONE, "\tCore %d -> Node %llu\n", i, numa_fw_cfg[core_offset + i]);
}
for (i = 0; i < num_nodes; i++) {
- V3_Print("\tMem (%p - %p) -> Node %d\n", (void *)region_start,
+ V3_Print(vm, VCORE_NONE, "\tMem (%p - %p) -> Node %d\n", (void *)region_start,
(void *)numa_fw_cfg[mem_offset + i], i);
region_start += numa_fw_cfg[mem_offset + i];
break;
}
+ case MOV_MEM2AL_8:
+ case MOV_MEM2AX: {
+
+ /* Use AX for destination operand */
+ instr->dst_operand.size = operand_width;
+ instr->dst_operand.type = REG_OPERAND;
+ instr->dst_operand.operand = (addr_t)&(core->vm_regs.rax);
+ instr->dst_operand.write = 1;
+
+ /* Get the correct offset -- (seg + offset) */
+ struct v3_segment * src_reg = get_instr_segment(core, instr);
+ addr_t offset = 0;
+
+ if (addr_width == 2) {
+ offset = *(uint16_t *)instr_ptr;
+ } else if (addr_width == 4) {
+ offset = *(uint32_t *)instr_ptr;
+ } else if (addr_width == 8) {
+ offset = *(uint64_t *)instr_ptr;
+ } else {
+ PrintError(core->vm_info, core, "illegal address width for %s (width=%d)\n",
+ op_form_to_str(form), addr_width);
+ return -1;
+ }
+
+ instr->src_operand.operand = ADDR_MASK(get_addr_linear(core, offset, src_reg),
+ get_addr_width(core, instr));
+
+ instr->src_operand.read = 1;
+ instr->src_operand.type = MEM_OPERAND;
+ instr->src_operand.size = addr_width;
+
+ instr_ptr += addr_width;
+ instr->num_operands = 2;
+
+ break;
+ }
+ case MOV_AL2MEM_8:
+ case MOV_AX2MEM: {
+
+ /* Use AX for src operand */
+ instr->src_operand.size = operand_width;
+ instr->src_operand.type = REG_OPERAND;
+ instr->src_operand.operand = (addr_t)&(core->vm_regs.rax);
+ instr->src_operand.write = 1;
+
+ /* Get the correct offset -- (seg + offset) */
+ struct v3_segment * dst_reg = get_instr_segment(core, instr);
+ addr_t offset = 0;
+
+ if (addr_width == 2) {
+ offset = *(uint16_t *)instr_ptr;
+ } else if (addr_width == 4) {
+ offset = *(uint32_t *)instr_ptr;
+ } else if (addr_width == 8) {
+ offset = *(uint64_t *)instr_ptr;
+ } else {
+ PrintError(core->vm_info, core, "illegal address width for %s (width=%d)\n",
+ op_form_to_str(form), addr_width);
+ return -1;
+ }
+
+ instr->dst_operand.operand = ADDR_MASK(get_addr_linear(core, offset, dst_reg),
+ get_addr_width(core, instr));
+
+ instr->dst_operand.read = 1;
+ instr->dst_operand.type = MEM_OPERAND;
+ instr->dst_operand.size = addr_width;
+
+ instr_ptr += addr_width;
+ instr->num_operands = 2;
+
+ break;
+ }
case MOVSX_8:
case MOVZX_8: {
uint8_t reg_code = 0;