#include <linux/proc_fs.h>
+#include <palacios/vmm.h>
+
#include "palacios.h"
#include "mm.h"
#include "vm.h"
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;
+static struct proc_dir_entry *dir = 0;
struct class * v3_class = NULL;
static struct cdev ctrl_dev;
case V3_CREATE_GUEST:{
int vm_minor = 0;
struct v3_guest_img user_image;
- struct v3_guest * guest = kmalloc(sizeof(struct v3_guest), GFP_KERNEL);
+ struct v3_guest * guest = palacios_alloc(sizeof(struct v3_guest));
if (IS_ERR(guest)) {
ERROR("Palacios: Error allocating Kernel guest_image\n");
if (vm_minor == -1) {
ERROR("Palacios Error: Too many VMs are currently running\n");
- return -EFAULT;
+ goto out_err;
}
guest->vm_dev = MKDEV(v3_major_num, vm_minor);
if (copy_from_user(&user_image, argp, sizeof(struct v3_guest_img))) {
ERROR("Palacios Error: copy from user error getting guest image...\n");
- return -EFAULT;
+ goto out_err1;
}
guest->img_size = user_image.size;
if (IS_ERR(guest->img)) {
ERROR("Palacios Error: Could not allocate space for guest image\n");
- return -EFAULT;
+ goto out_err1;
}
if (copy_from_user(guest->img, user_image.guest_data, guest->img_size)) {
ERROR("Palacios: Error loading guest data\n");
- return -EFAULT;
+ goto out_err2;
}
strncpy(guest->name, user_image.name, 127);
if (create_palacios_vm(guest) == -1) {
ERROR("Palacios: Error creating guest\n");
- return -EFAULT;
+ goto out_err2;
}
return vm_minor;
+
+
+out_err2:
+ vfree(guest->img);
+out_err1:
+ guest_map[vm_minor] = NULL;
+out_err:
+ palacios_free(guest);
+
+ return -1;
+
break;
}
case V3_FREE_GUEST: {
unsigned long vm_idx = arg;
- struct v3_guest * guest = guest_map[vm_idx];
+ struct v3_guest * guest;
+
+ if (vm_idx > MAX_VMS) {
+ ERROR("Invalid VM index: %ld\n", vm_idx);
+ return -1;
+ }
+
+ guest = guest_map[vm_idx];
+
+ if (!guest) {
+ ERROR("No VM at index %ld\n",vm_idx);
+ return -1;
+ }
INFO("Freeing VM (%s) (%p)\n", guest->name, guest);
- free_palacios_vm(guest);
+ if (free_palacios_vm(guest)<0) {
+ ERROR("Cannot free guest at index %ld\n",vm_idx);
+ return -1;
+ }
+
guest_map[vm_idx] = NULL;
break;
}
break;
}
- default:
- ERROR("\tUnhandled\n");
+ case V3_RESET_MEMORY: {
+ if (palacios_init_mm() == -1) {
+ ERROR("Error resetting Palacios memory\n");
+ return -EFAULT;
+ }
+ break;
+ }
+
+ default: {
+ struct global_ctrl * ctrl = get_global_ctrl(ioctl);
+
+ if (ctrl) {
+ return ctrl->handler(ioctl, arg);
+ }
+
+ WARNING("\tUnhandled global ctrl cmd: %d\n", ioctl);
+
return -EINVAL;
+ }
}
return 0;
+struct proc_dir_entry *palacios_get_procdir(void)
+{
+ return dir;
+}
+
+
+#define MAX_VCORES 32
+
static int read_guests(char * buf, char ** start, off_t off, int count,
int * eof, void * data)
{
int len = 0;
unsigned int i = 0;
+
+ struct v3_vm_state *s =palacios_alloc(sizeof(struct v3_vm_state)+MAX_VCORES*sizeof(struct v3_vcore_state));
+
+ if (!s) {
+ ERROR("No space for state structure\n");
+ goto out;
+ }
for(i = 0; i < MAX_VMS; i++) {
- if (guest_map[i] != NULL) {
- if (len<count) {
- len += snprintf(buf+len, count-len,
- "%s\t/dev/v3-vm%d\n",
- guest_map[i]->name, i);
+ if (guest_map[i] != NULL) {
+ if (len>=count) {
+ goto out;
+ } else {
+ len += snprintf(buf+len, count-len,
+ "%s\t/dev/v3-vm%d ",
+ guest_map[i]->name, i);
+
+ if (len>=count) {
+ *(buf+len-1)='\n';
+ goto out;
+ } else {
+ // Get extended data
+ s->num_vcores=MAX_VCORES; // max we can handle
+ if (v3_get_state_vm(guest_map[i]->v3_ctx, s)) {
+ ERROR("Cannot get VM info\n");
+ *(buf+len-1)='\n';
+ goto out;
+ } else {
+ unsigned long j;
+
+ len+=snprintf(buf+len, count-len,
+ "%s [0x%p-0x%p] %lu vcores ",
+ s->state==V3_VM_INVALID ? "INVALID" :
+ s->state==V3_VM_RUNNING ? "running" :
+ s->state==V3_VM_STOPPED ? "stopped" :
+ s->state==V3_VM_PAUSED ? "paused" :
+ s->state==V3_VM_ERROR ? "ERROR" :
+ s->state==V3_VM_SIMULATING ? "simulating" : "UNKNOWN",
+ s->mem_base_paddr, s->mem_base_paddr+s->mem_size-1,
+ s->num_vcores);
+ if (len>=count) {
+ *(buf+len-1)='\n';
+ goto out;
+ }
+ for (j=0;j<s->num_vcores;j++) {
+ len+=snprintf(buf+len, count-len,
+ "[vcore %lu %s on pcore %lu %llu exits rip=0x%p %s %s %s] ",
+ j,
+ s->vcore[j].state==V3_VCORE_INVALID ? "INVALID" :
+ s->vcore[j].state==V3_VCORE_RUNNING ? "running" :
+ s->vcore[j].state==V3_VCORE_STOPPED ? "stopped" : "UNKNOWN",
+ s->vcore[j].pcore,
+ s->vcore[j].num_exits,
+ s->vcore[j].last_rip,
+ s->vcore[j].cpu_mode==V3_VCORE_CPU_REAL ? "real" :
+ s->vcore[j].cpu_mode==V3_VCORE_CPU_PROTECTED ? "protected" :
+ s->vcore[j].cpu_mode==V3_VCORE_CPU_PROTECTED_PAE ? "protectedpae" :
+ s->vcore[j].cpu_mode==V3_VCORE_CPU_LONG ? "long" :
+ s->vcore[j].cpu_mode==V3_VCORE_CPU_LONG_32_COMPAT ? "long32" :
+ s->vcore[j].cpu_mode==V3_VCORE_CPU_LONG_16_COMPAT ? "long16" : "UNKNOWN",
+ s->vcore[j].mem_mode==V3_VCORE_MEM_MODE_PHYSICAL ? "physical" :
+ s->vcore[j].mem_mode==V3_VCORE_MEM_MODE_VIRTUAL ? "virtual" : "UNKNOWN",
+ s->vcore[j].mem_state==V3_VCORE_MEM_STATE_SHADOW ? "shadow" :
+ s->vcore[j].mem_state==V3_VCORE_MEM_STATE_NESTED ? "nested" : "UNKNOWN");
+ if (len>=count) {
+ *(buf+len-1)='\n';
+ goto out;
+ }
+ }
+
+ *(buf+len-1)='\n';
+
}
+ }
}
+ }
}
-
+
+ out:
+ if (s) { palacios_free(s); }
+
return len;
}
extern u32 pg_frees;
extern u32 mallocs;
extern u32 frees;
+ int i = 0;
+ struct v3_guest * guest;
+ dev_t dev;
- // should probably try to stop any guests
+ /* Stop and free any running VMs */
+ for (i = 0; i < MAX_VMS; i++) {
+ if (guest_map[i] != NULL) {
+ guest = (struct v3_guest *)guest_map[i];
+ if (v3_stop_vm(guest->v3_ctx) < 0)
+ ERROR("Couldn't stop VM %d\n", i);
+ free_palacios_vm(guest);
+ guest_map[i] = NULL;
+ }
+ }
- dev_t dev = MKDEV(v3_major_num, MAX_VMS + 1);
+ dev = MKDEV(v3_major_num, MAX_VMS + 1);
INFO("Removing V3 Control device\n");