Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Merge branch 'devel' of newskysaw.cs.northwestern.edu:/home/palacios/palacios into...
Peter Dinda [Thu, 27 Oct 2011 19:24:52 +0000 (14:24 -0500)]
25 files changed:
Kconfig
linux_module/iface-keyed-stream.c
linux_module/mm.c
linux_module/palacios-stubs.c
linux_module/vm.c
palacios/include/palacios/vmm_ethernet.h
palacios/include/palacios/vmm_instr_decoder.h
palacios/include/palacios/vmm_msr.h
palacios/include/palacios/vmm_time.h
palacios/src/devices/Kconfig
palacios/src/devices/apic.c
palacios/src/devices/lnx_virtio_nic.c
palacios/src/devices/lnx_virtio_vnet.c
palacios/src/palacios/svm.c
palacios/src/palacios/svm_io.c
palacios/src/palacios/svm_msr.c
palacios/src/palacios/vmm.c
palacios/src/palacios/vmm_msr.c
palacios/src/palacios/vmm_time.c
palacios/src/palacios/vmm_v3dec.c
palacios/src/palacios/vmx.c
palacios/src/palacios/vmx_io.c
palacios/src/palacios/vmx_msr.c
palacios/src/vnet/vnet_core.c
utils/guest_creator/default.xml

diff --git a/Kconfig b/Kconfig
index b7fc9a0..8518fd8 100644 (file)
--- a/Kconfig
+++ b/Kconfig
@@ -212,16 +212,19 @@ endmenu
 
 
 menu "Time Management"
-config VIRTUALIZE_TIME
-       bool "Enable Time virtualization"
+config TIME_DILATION
+       bool "Control Guest/Host Time Offseting"
        default n
+       depends on EXPERIMENTAL
        help
-          Enables the timer virtualization extensions
+           Controls the relative speeds of the guest and host processor
+           to allow the VM to provide the illusion of the guest seeing time
+           pass at a different rate than the host system does.
+
 config TIME_HIDE_VM_COST
         bool "Hide VMM Run Cost"
        default n
-       depends on VIRTUALIZE_TIME
+       depends on EXPERIMENTAL 
        help
            Offset guest time from host time sufficiently to hide the cost of
            running in the virtual machine. This can aid the consistency of
@@ -231,12 +234,12 @@ config TIME_HIDE_VM_COST
 config TIME_VIRTUALIZE_TSC
        bool "Fully virtualize guest TSC"
        default n
-       depends on VIRTUALIZE_TIME
+       depends on EXPERIMENTAL
        help
            Virtualize the processor time stamp counter in the guest, 
            generally increasing consistency between various time sources 
            but also potentially making guest time run slower than real time.
-        
+       
 endmenu
 
 
index fc0e1b9..bb19e70 100644 (file)
@@ -876,7 +876,6 @@ static unsigned int keyed_stream_poll_user(struct file *filp, poll_table *wait)
     return 0;
 }
 
-
 static int keyed_stream_ioctl_user(struct inode *inode, struct file *filp, unsigned int ioctl, unsigned long arg)
 {
     void __user *argp = (void __user *)arg;
@@ -986,6 +985,11 @@ static int keyed_stream_ioctl_user(struct inode *inode, struct file *filp, unsig
     }
 }
 
+static long keyed_stream_compat_ioctl_user(struct file * filp, unsigned int ioctl, unsigned long arg)
+{
+       return keyed_stream_ioctl_user(NULL, filp, ioctl, arg);
+}
+
 static int keyed_stream_release_user(struct inode *inode, struct file *filp)
 {
     struct user_keyed_stream *s = filp->private_data;
@@ -1007,7 +1011,11 @@ static int keyed_stream_release_user(struct inode *inode, struct file *filp)
 
 static struct file_operations user_keyed_stream_fops = {
     .poll = keyed_stream_poll_user,
+#ifdef HAVE_COMPAT_IOCTL
+    .compat_ioctl = keyed_stream_compat_ioctl_user,
+#else
     .ioctl = keyed_stream_ioctl_user,
+#endif
     .release = keyed_stream_release_user,
 };
 
index 04dcab3..e4852c3 100644 (file)
@@ -107,25 +107,25 @@ uintptr_t alloc_palacios_pgs(u64 num_pages, u32 alignment) {
     
        WARN(!pgs, "Could not allocate pages\n");
        
-       printk("%llu pages (order=%d) aquired from alloc_pages\n", 
-              num_pages, order);
+       /* printk("%llu pages (order=%d) aquired from alloc_pages\n", 
+              num_pages, order); */
 
        addr = page_to_pfn(pgs) << PAGE_SHIFT; 
     } else {
-       printk("Allocating %llu pages from bitmap allocator\n", num_pages);
+       //printk("Allocating %llu pages from bitmap allocator\n", num_pages);
        //addr = pool.base_addr;
        addr = alloc_contig_pgs(num_pages, alignment);
     }
 
 
-    printk("Returning from alloc addr=%p, vaddr=%p\n", (void *)addr, __va(addr));
+    //printk("Returning from alloc addr=%p, vaddr=%p\n", (void *)addr, __va(addr));
     return addr;
 }
 
 
 
 void free_palacios_pgs(uintptr_t pg_addr, int num_pages) {
-    printk("Freeing Memory page %p\n", (void *)pg_addr);
+    //printk("Freeing Memory page %p\n", (void *)pg_addr);
 
     if ((pg_addr >= pool.base_addr) && 
        (pg_addr < pool.base_addr + (4096 * pool.num_pages))) {
index 21aa4fd..2499339 100644 (file)
@@ -218,7 +218,11 @@ palacios_start_thread_on_cpu(int cpu_id,
        return NULL;
     }
 
-    set_cpus_allowed_ptr(thread, cpumask_of(cpu_id));
+    if (set_cpus_allowed_ptr(thread, cpumask_of(cpu_id)) != 0) {
+       kthread_stop(thread);
+       return NULL;
+    }
+
     wake_up_process(thread);
 
     return thread;
index 9869334..a1af564 100644 (file)
@@ -130,7 +130,7 @@ static long v3_vm_ioctl(struct file * filp,
        case V3_VM_LAUNCH: {
            printk("palacios: launching vm\n");
 
-           if (v3_start_vm(guest->v3_ctx, 0xfffffffe) < 0) { 
+           if (v3_start_vm(guest->v3_ctx, (0x1 << num_online_cpus()) - 1) < 0) { 
                printk("palacios: launch of vm failed\n");
                return -1;
            }
index dadb775..c4725a9 100644 (file)
@@ -28,9 +28,9 @@
 #define ETH_ALEN 6
 
 #define MIN_MTU 68
-#define MAX_MTU 65535
+#define MAX_MTU 65536
 
-#define MAX_PACKET_LEN (MAX_MTU)
+#define MAX_PACKET_LEN (MAX_MTU + ETHERNET_HEADER_LEN)
 
 #ifdef V3_CONFIG_VNET
 extern int net_debug;
index 6e33c46..53831c4 100644 (file)
@@ -191,6 +191,7 @@ static int get_operand_width(struct guest_info * info, struct x86_instr * instr,
        case XOR_MEM2_8:
        case XOR_IMM2_8:
        case INC_8:
+       case INT:
        case DEC_8:
        case NEG_8:
        case NOT_8:
@@ -310,7 +311,7 @@ static int get_operand_width(struct guest_info * info, struct x86_instr * instr,
                    return -1;
            }
 
-       case INT:
+       //case INT:
        case MOV_DR2:
        case MOV_2DR:
        case MOV_CR2:
index 0d2391a..87a8a7e 100644 (file)
 #include <palacios/vmm_types.h>
 #include <palacios/vmm_list.h>
 
+#define SYSENTER_CS_MSR 0x00000174
+#define SYSENTER_ESP_MSR 0x00000175
+#define SYSENTER_EIP_MSR 0x00000176
+#define EFER_MSR 0xc0000080
+#define IA32_STAR_MSR 0xc0000081
+#define IA32_LSTAR_MSR 0xc0000082
+#define IA32_CSTAR_MSR 0xc0000083 
+#define IA32_FMASK_MSR 0xc0000084
+#define FS_BASE_MSR 0xc0000100
+#define GS_BASE_MSR 0xc0000101
+#define IA32_KERN_GS_BASE_MSR 0xc0000102
+
+
 struct guest_info;
 struct v3_vm_info;
 
index 329fce6..33ffa2c 100644 (file)
@@ -91,7 +91,7 @@ static inline uint64_t v3_get_host_time(struct vm_time *t) {
 }
 
 // Returns *monotonic* guest time.
-static inline uint64_t v3_get_guest_time(struct vm_time *t) {
+static inline uint64_t v3_compute_guest_time(struct vm_time *t, uint64_t ht) {
 #ifdef V3_CONFIG_TIME_HIDE_VM_COST
     V3_ASSERT(t->exit_time);
     return t->exit_time + t->guest_host_offset;
@@ -100,9 +100,17 @@ static inline uint64_t v3_get_guest_time(struct vm_time *t) {
 #endif
 }
 
+static inline uint64_t v3_get_guest_time(struct vm_time *t) {
+    return v3_compute_guest_time(t, v3_get_host_time(t));
+}
+
 // Returns the TSC value seen by the guest
+static inline uint64_t v3_compute_guest_tsc(struct vm_time *t, uint64_t ht) {
+    return v3_compute_guest_time(t, ht) + t->tsc_guest_offset;
+}
+
 static inline uint64_t v3_get_guest_tsc(struct vm_time *t) {
-    return v3_get_guest_time(t) + t->tsc_guest_offset;
+    return v3_compute_guest_tsc(t, v3_get_host_time(t));
 }
 
 // Returns offset of guest TSC from host TSC
index 23a88ff..e9b2dc8 100644 (file)
@@ -6,6 +6,13 @@ config APIC
        help 
          Includes the Virtual APIC device
 
+config APIC_ENQUEUE_MISSED_TMR_IRQS
+       bool "Enqueue missed APIC timer interrpts"
+       default n
+       depends on APIC
+       help
+         Make up missed APIC periodic timer interrupts on later 
+         exits into the virtual machine
 
 config DEBUG_APIC
        bool "APIC Debugging"
@@ -14,8 +21,6 @@ config DEBUG_APIC
        help 
          Enable debugging for the APIC
 
-
-
 config IO_APIC
        bool "IOAPIC"
        depends on APIC
index d83f0bd..5aa5e13 100644 (file)
@@ -1570,9 +1570,9 @@ static void apic_inject_timer_intr(struct guest_info *core,
     struct apic_dev_state * apic_dev = (struct apic_dev_state *)(priv_data);
     struct apic_state * apic = &(apic_dev->apics[core->vcpu_id]); 
     // raise irq
-    PrintDebug("apic %u: core %u: Raising APIC Timer interrupt (periodic=%d) (icnt=%d) (div=%d)\n",
+    PrintDebug("apic %u: core %u: Raising APIC Timer interrupt (periodic=%d) (icnt=%d)\n",
               apic->lapic_id.val, core->vcpu_id,
-              apic->tmr_vec_tbl.tmr_mode, apic->tmr_init_cnt, shift_num);
+              apic->tmr_vec_tbl.tmr_mode, apic->tmr_init_cnt);
 
     if (apic_intr_pending(core, priv_data)) {
         PrintDebug("apic %u: core %u: Overriding pending IRQ %d\n", 
@@ -1655,10 +1655,14 @@ static void apic_update_time(struct guest_info * core,
 
     if (tmr_ticks < apic->tmr_cur_cnt) {
        apic->tmr_cur_cnt -= tmr_ticks;
-       if (apic->missed_ints) {
+#ifdef V3_CONFIG_APIC_ENQUEUE_MISSED_TMR_IRQS
+       if (apic->missed_ints && !apic_intr_pending(core, priv_data)) {
+           PrintDebug("apic %u: core %u: Injecting queued APIC timer interrupt.\n",
+                      apic->lapic_id.val, core->vcpu_id);
            apic_inject_timer_intr(core, priv_data);
            apic->missed_ints--;
        }
+#endif /* CONFIG_APIC_ENQUEUE_MISSED_TMR_IRQS */ 
     } else {
        tmr_ticks -= apic->tmr_cur_cnt;
        apic->tmr_cur_cnt = 0;
@@ -1666,9 +1670,10 @@ static void apic_update_time(struct guest_info * core,
        apic_inject_timer_intr(core, priv_data);
 
        if (apic->tmr_vec_tbl.tmr_mode == APIC_TMR_PERIODIC) {
-           apic->missed_ints += tmr_ticks / apic->tmr_init_cnt;
+           int queued_ints = tmr_ticks / apic->tmr_init_cnt;
            tmr_ticks = tmr_ticks % apic->tmr_init_cnt;
            apic->tmr_cur_cnt = apic->tmr_init_cnt - tmr_ticks;
+           apic->missed_ints += queued_ints;
        }
     }
 
index 6300eb8..8032b13 100644 (file)
@@ -1,3 +1,4 @@
+
 /* 
  * This file is part of the Palacios Virtual Machine Monitor developed
  * by the V3VEE Project with funding from the United States National 
@@ -131,8 +132,6 @@ struct virtio_net_state {
     uint8_t mergeable_rx_bufs;
 
     struct v3_timer * timer;
-    struct vnet_thread * poll_thread;
-
     struct nic_statistics stats;
 
     struct v3_dev_net_ops * net_ops;
@@ -330,8 +329,6 @@ static int handle_pkt_tx(struct guest_info * core,
        virtio_state->stats.rx_interrupts ++;
     }
 
-    V3_Print("Virtio Intr Line %d\n", virtio_state->pci_dev->config_header.intr_line);
-
     if(txed > 0) {
        V3_Net_Print(2, "Virtio Handle TX: txed pkts: %d, left %d\n", txed, left);
     }
@@ -425,8 +422,8 @@ static int virtio_io_write(struct guest_info *core,
                                       pfn, page_addr);
                    if(virtio->tx_notify == 0){
                        disable_cb(&virtio->tx_vq);
-                       vnet_thread_wakeup(virtio->poll_thread);
                    }
+                   virtio->status = 1;
                    break;
                case 2:
                    virtio_setup_queue(core, virtio, 
@@ -760,7 +757,12 @@ static struct v3_device_ops dev_ops = {
 static int virtio_poll(int quote, void * data){
     struct virtio_net_state * virtio  = (struct virtio_net_state *)data;
 
-    return handle_pkt_tx(&(virtio->vm->cores[0]), virtio, quote);
+    if (virtio->status) {
+
+       return handle_pkt_tx(&(virtio->vm->cores[0]), virtio, quote);
+    } 
+
+    return 0;
 }
 
 static int register_dev(struct virtio_dev_state * virtio, 
@@ -838,7 +840,6 @@ static int register_dev(struct virtio_dev_state * virtio,
     return 0;
 }
 
-
 #define RATE_UPPER_THRESHOLD 10  /* 10000 pkts per second, around 100Mbits */
 #define RATE_LOWER_THRESHOLD 1
 #define PROFILE_PERIOD 10000 /*us*/
@@ -870,7 +871,6 @@ static void virtio_nic_timer(struct guest_info * core,
            V3_Print("Virtio NIC: Switch TX to VMM driven mode\n");
            disable_cb(&(net_state->tx_vq));
            net_state->tx_notify = 0;
-           vnet_thread_wakeup(net_state->poll_thread);
        }
 
        if(tx_rate < RATE_LOWER_THRESHOLD && net_state->tx_notify == 0){
@@ -924,11 +924,12 @@ static int connect_fn(struct v3_vm_info * info,
     net_state->net_ops = ops;
     net_state->backend_data = private_data;
     net_state->virtio_dev = virtio;
-    net_state->tx_notify = 0;
-    net_state->rx_notify = 0;
+    
+    net_state->tx_notify = 1;
+    net_state->rx_notify = 1;
        
     net_state->timer = v3_add_timer(&(info->cores[0]),
-                                   &timer_ops,net_state);
+                                &timer_ops,net_state);
 
     ops->recv = virtio_rx;
     ops->poll = virtio_poll;
@@ -938,8 +939,6 @@ static int connect_fn(struct v3_vm_info * info,
     ops->config.fnt_mac = V3_Malloc(ETH_ALEN);  
     memcpy(ops->config.fnt_mac, virtio->mac, ETH_ALEN);
 
-    net_state->status = 1;
-
     return 0;
 }
 
index e604b9e..7b6d75c 100644 (file)
@@ -303,7 +303,7 @@ static int do_tx_pkts(struct guest_info * core,
        memcpy(pkt.header, virtio_pkt->pkt, ETHERNET_HEADER_LEN);
        pkt.data = virtio_pkt->pkt;
 
-       v3_vnet_send_pkt(&pkt, NULL, 1);
+       v3_vnet_send_pkt(&pkt, NULL);
        
        q->used->ring[q->used->index % q->queue_size].id = q->avail->ring[q->cur_avail_idx % q->queue_size];
        q->used->ring[q->used->index % q->queue_size].length = pkt_desc->length; // What do we set this to????
index 6064855..d583657 100644 (file)
@@ -311,6 +311,19 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info * core) {
        &v3_handle_vm_cr_read,
        &v3_handle_vm_cr_write, 
        core);
+
+
+    {
+       v3_hook_msr(core->vm_info, IA32_STAR_MSR, NULL, NULL, NULL);
+       v3_hook_msr(core->vm_info, IA32_LSTAR_MSR, NULL, NULL, NULL);
+       v3_hook_msr(core->vm_info, IA32_FMASK_MSR, NULL, NULL, NULL);
+       v3_hook_msr(core->vm_info, IA32_KERN_GS_BASE_MSR, NULL, NULL, NULL);
+       v3_hook_msr(core->vm_info, IA32_CSTAR_MSR, NULL, NULL, NULL);
+
+       v3_hook_msr(core->vm_info, SYSENTER_CS_MSR, NULL, NULL, NULL);
+       v3_hook_msr(core->vm_info, SYSENTER_ESP_MSR, NULL, NULL, NULL);
+       v3_hook_msr(core->vm_info, SYSENTER_EIP_MSR, NULL, NULL, NULL);
+    }
 }
 
 
@@ -509,6 +522,7 @@ int v3_svm_enter(struct guest_info * info) {
     vmcb_ctrl_t * guest_ctrl = GET_VMCB_CTRL_AREA((vmcb_t*)(info->vmm_data));
     vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data)); 
     addr_t exit_code = 0, exit_info1 = 0, exit_info2 = 0;
+    sint64_t tsc_offset;
 
     // Conditionally yield the CPU if the timeslice has expired
     v3_yield_cond(info);
@@ -569,7 +583,8 @@ int v3_svm_enter(struct guest_info * info) {
 #endif
 
     v3_time_enter_vm(info);
-    // guest_ctrl->TSC_OFFSET = v3_tsc_host_offset(&info->time_state);
+    tsc_offset = v3_tsc_host_offset(&info->time_state);
+    guest_ctrl->TSC_OFFSET = tsc_offset;
 
 
     //V3_Print("Calling v3_svm_launch\n");
index 405acc2..e273466 100644 (file)
@@ -49,7 +49,7 @@ int v3_init_svm_io_map(struct v3_vm_info * vm) {
     vm->io_map.update_map = update_map;
 
     vm->io_map.arch_data = V3_VAddr(V3_AllocPages(3));
-    memset(vm->io_map.arch_data, 0, PAGE_SIZE_4KB * 3);
+    memset(vm->io_map.arch_data, 0xff, PAGE_SIZE_4KB * 3);
 
 
     v3_refresh_io_map(vm);
@@ -69,13 +69,6 @@ int v3_handle_svm_io_in(struct guest_info * core, struct svm_io_info * io_info)
     struct v3_io_hook * hook = v3_get_io_hook(core->vm_info, io_info->port);
     int read_size = 0;
 
-    if (hook == NULL) {
-       PrintError("Hook Not present for in on port 0x%x\n", io_info->port);
-       // error, we should not have exited on this port
-       return -1;
-    }
-
-
     if (io_info->sz8) { 
        read_size = 1;
     } else if (io_info->sz16) {
@@ -86,11 +79,20 @@ int v3_handle_svm_io_in(struct guest_info * core, struct svm_io_info * io_info)
 
     PrintDebug("IN of %d bytes on port %d (0x%x)\n", read_size, io_info->port, io_info->port);
 
-    if (hook->read(core, io_info->port, &(core->vm_regs.rax), read_size, hook->priv_data) != read_size) {
-       // not sure how we handle errors.....
-       PrintError("Read Failure for in on port 0x%x\n", io_info->port);
-       return -1;
+    if (hook == NULL) {
+       PrintDebug("IN operation on unhooked IO port 0x%x\n", io_info->port);
+
+       /* What are the HW semantics for an IN on an invalid port? 
+        *  Do we need to clear the register value or leave it untouched??? 
+        */
+    } else {
+       if (hook->read(core, io_info->port, &(core->vm_regs.rax), read_size, hook->priv_data) != read_size) {
+           // not sure how we handle errors.....
+           PrintError("Read Failure for in on port 0x%x\n", io_info->port);
+           return -1;
+       }
     }
+    
 
     return 0;
 }
@@ -121,15 +123,7 @@ int v3_handle_svm_io_ins(struct guest_info * core, struct svm_io_info * io_info)
     if (flags->df) {
        direction = -1;
     }
-
-
-    if (hook == NULL) {
-       PrintError("Hook Not present for ins on port 0x%x\n", io_info->port);
-       // error, we should not have exited on this port
-       return -1;
-    }
-
-
+    
 
     if (v3_gva_to_hva(core, get_addr_linear(core, core->rip, &(core->segments.cs)), &inst_ptr) == -1) {
        PrintError("Can't access instruction\n");
@@ -198,7 +192,6 @@ int v3_handle_svm_io_ins(struct guest_info * core, struct svm_io_info * io_info)
        //rep_num = info->vm_regs.rcx;
     }
 
-
     PrintDebug("INS size=%d for %d steps\n", read_size, rep_num);
 
     while (rep_num > 0) {
@@ -213,12 +206,19 @@ int v3_handle_svm_io_ins(struct guest_info * core, struct svm_io_info * io_info)
            return -1;
        }
 
-       if (hook->read(core, io_info->port, (char *)host_addr, read_size, hook->priv_data) != read_size) {
-           // not sure how we handle errors.....
-           PrintError("Read Failure for ins on port 0x%x\n", io_info->port);
-           return -1;
+       if (hook == NULL) {
+           PrintDebug("INS operation on unhooked IO port 0x%x\n", io_info->port);
+           /* What are the HW semantics for an INS on an invalid port? 
+            *  Do we need to clear the memory region or leave it untouched??? 
+            */     
+       } else {
+           if (hook->read(core, io_info->port, (char *)host_addr, read_size, hook->priv_data) != read_size) {
+               // not sure how we handle errors.....
+               PrintError("Read Failure for ins on port 0x%x\n", io_info->port);
+               return -1;
+           }
        }
-
+    
        core->vm_regs.rdi += (read_size * direction);
 
        if (io_info->rep) {
@@ -235,13 +235,6 @@ int v3_handle_svm_io_out(struct guest_info * core, struct svm_io_info * io_info)
     struct v3_io_hook * hook = v3_get_io_hook(core->vm_info, io_info->port);
     int write_size = 0;
 
-    if (hook == NULL) {
-       PrintError("Hook Not present for out on port 0x%x\n", io_info->port);
-       // error, we should not have exited on this port
-       return -1;
-    }
-
-
     if (io_info->sz8) { 
        write_size = 1;
     } else if (io_info->sz16) {
@@ -252,11 +245,16 @@ int v3_handle_svm_io_out(struct guest_info * core, struct svm_io_info * io_info)
 
     PrintDebug("OUT of %d bytes on  port %d (0x%x)\n", write_size, io_info->port, io_info->port);
 
-    if (hook->write(core, io_info->port, &(core->vm_regs.rax), write_size, hook->priv_data) != write_size) {
-       // not sure how we handle errors.....
-       PrintError("Write Failure for out on port 0x%x\n", io_info->port);
-       return -1;
+    if (hook == NULL) {
+       PrintDebug("OUT operation on unhooked IO port 0x%x\n", io_info->port);
+    } else {
+       if (hook->write(core, io_info->port, &(core->vm_regs.rax), write_size, hook->priv_data) != write_size) {
+           // not sure how we handle errors.....
+           PrintError("Write Failure for out on port 0x%x\n", io_info->port);
+           return -1;
+       }
     }
+    
 
     return 0;
 }
@@ -286,13 +284,6 @@ int v3_handle_svm_io_outs(struct guest_info * core, struct svm_io_info * io_info
        direction = -1;
     }
 
-
-    if (hook == NULL) {
-       PrintError("Hook Not present for outs on port 0x%x\n", io_info->port);
-       // error, we should not have exited on this port
-       return -1;
-    }
-
     PrintDebug("OUTS on  port %d (0x%x)\n", io_info->port, io_info->port);
 
     if (io_info->sz8) { 
@@ -373,11 +364,16 @@ int v3_handle_svm_io_outs(struct guest_info * core, struct svm_io_info * io_info
            return -1;
        }
 
-       if (hook->write(core, io_info->port, (char*)host_addr, write_size, hook->priv_data) != write_size) {
-           // not sure how we handle errors.....
-           PrintError("Write Failure for outs on port 0x%x\n", io_info->port);
-           return -1;
+       if (hook == NULL) {
+           PrintDebug("OUTS operation on unhooked IO port 0x%x\n", io_info->port);
+       } else {
+           if (hook->write(core, io_info->port, (char*)host_addr, write_size, hook->priv_data) != write_size) {
+               // not sure how we handle errors.....
+               PrintError("Write Failure for outs on port 0x%x\n", io_info->port);
+               return -1;
+           }
        }
+       
 
        core->vm_regs.rsi += write_size * direction;
 
index 345ab1a..2ffcfac 100644 (file)
@@ -82,7 +82,7 @@ int v3_init_svm_msr_map(struct v3_vm_info * vm) {
     msr_map->update_map = update_map;
 
     msr_map->arch_data = V3_VAddr(V3_AllocPages(2));  
-    memset(msr_map->arch_data, 0, PAGE_SIZE_4KB * 2);
+    memset(msr_map->arch_data, 0xff, PAGE_SIZE_4KB * 2);
 
     v3_refresh_msr_map(vm);
 
index 341996a..afc8c1c 100644 (file)
@@ -255,7 +255,11 @@ int v3_start_vm(struct v3_vm_info * vm, unsigned int cpu_mask) {
        int minor = i % 8;
        
        if (core_mask[major] & (0x1 << minor)) {
-           avail_cores++;
+           if (v3_cpu_types[i] == V3_INVALID_CPU) {
+               core_mask[major] &= ~(0x1 << minor);
+           } else {
+               avail_cores++;
+           }
        }
     }
 
@@ -323,6 +327,12 @@ int v3_start_vm(struct v3_vm_info * vm, unsigned int cpu_mask) {
        vcore_id--;
     }
 
+    if (vcore_id >= 0) {
+       PrintError("Error starting VM: Not enough available CPU cores\n");
+       v3_stop_vm(vm);
+       return -1;
+    }
+
 
     return 0;
 
@@ -563,11 +573,10 @@ void v3_yield_cond(struct guest_info * info) {
     cur_cycle = v3_get_host_time(&info->time_state);
 
     if (cur_cycle > (info->yield_start_cycle + info->vm_info->yield_cycle_period)) {
-
-       /*
-         PrintDebug("Conditional Yield (cur_cyle=%p, start_cycle=%p, period=%p)\n", 
-         (void *)cur_cycle, (void *)info->yield_start_cycle, (void *)info->yield_cycle_period);
-       */
+       //PrintDebug("Conditional Yield (cur_cyle=%p, start_cycle=%p, period=%p)\n", 
+       //           (void *)cur_cycle, (void *)info->yield_start_cycle, 
+       //         (void *)info->yield_cycle_period);
+       
        V3_Yield();
        info->yield_start_cycle = v3_get_host_time(&info->time_state);
     }
index 68d4767..290398e 100644 (file)
@@ -51,23 +51,23 @@ int v3_handle_msr_write(struct guest_info * info) {
     uint32_t msr_num = info->vm_regs.rcx;
     struct v3_msr msr_val;
     struct v3_msr_hook * hook = NULL;
+    
+    msr_val.value = 0;
 
     PrintDebug("MSR write for msr 0x%x\n", msr_num);
 
     hook = v3_get_msr_hook(info->vm_info, msr_num);
 
-    if (!hook) {
-        PrintError("Hook for MSR write %d not found\n", msr_num);
-        return -1;
-    }
-
-    msr_val.value = 0;
-    msr_val.lo = info->vm_regs.rax;
-    msr_val.hi = info->vm_regs.rdx;
-
-    if (hook->write(info, msr_num, msr_val, hook->priv_data) == -1) {
-        PrintError("Error in MSR hook Write\n");
-        return -1;
+    if (hook == NULL) {
+        PrintError("Write to unhooked MSR 0x%x\n", msr_num);
+    } else {
+       msr_val.lo = info->vm_regs.rax;
+       msr_val.hi = info->vm_regs.rdx;
+       
+       if (hook->write(info, msr_num, msr_val, hook->priv_data) == -1) {
+           PrintError("Error in MSR hook Write\n");
+           return -1;
+       }
     }
 
     info->rip += 2;
@@ -81,20 +81,19 @@ int v3_handle_msr_read(struct guest_info * info) {
     struct v3_msr msr_val;
     struct v3_msr_hook * hook = NULL;
 
-    hook = v3_get_msr_hook(info->vm_info, msr_num);
-
-    if (!hook) {
-        PrintError("Hook for MSR read 0x%x not found\n", msr_num);
-        return -1;
-    }
-
     msr_val.value = 0;
 
-    if (hook->read(info, msr_num, &msr_val, hook->priv_data) == -1) {
-        PrintError("Error in MSR hook Read\n");
-        return -1;
+    hook = v3_get_msr_hook(info->vm_info, msr_num);
+    
+    if (hook == NULL) {
+        PrintError("Read from unhooked MSR 0x%x\n", msr_num);  
+    } else {
+       if (hook->read(info, msr_num, &msr_val, hook->priv_data) == -1) {
+           PrintError("Error in MSR hook Read\n");
+           return -1;
+       }
     }
-
+    
     info->vm_regs.rax = msr_val.lo;
     info->vm_regs.rdx = msr_val.hi;
 
index fa8f5cd..2295b3f 100644 (file)
@@ -99,17 +99,18 @@ int v3_start_time(struct guest_info * info) {
 int v3_offset_time( struct guest_info * info, sint64_t offset )
 {
     struct vm_time * time_state = &(info->time_state);
-//    PrintDebug("Adding additional offset of %lld to guest time.\n", offset);
+    PrintDebug("Adding additional offset of %lld to guest time.\n", offset);
     time_state->guest_host_offset += offset;
     return 0;
 }
 
-static uint64_t compute_target_host_time(struct guest_info * info)
+#ifdef V3_CONFIG_TIME_DILATION
+static uint64_t compute_target_host_time(struct guest_info * info, uint64_t guest_time)
 {
     struct vm_time * time_state = &(info->time_state);
     uint64_t guest_elapsed, desired_elapsed;
     
-    guest_elapsed = (v3_get_guest_time(time_state) - time_state->initial_time);
+    guest_elapsed = (guest_time - time_state->initial_time);
     desired_elapsed = (guest_elapsed * time_state->host_cpu_freq) / time_state->guest_cpu_freq;
     return time_state->initial_time + desired_elapsed;
 }
@@ -133,28 +134,25 @@ static int yield_host_time(struct guest_info * info) {
     uint64_t host_time, target_host_time;
     uint64_t guest_time, old_guest_time;
 
-    /* Compute the target host time given how much time has *already*
-     * passed in the guest */
-    target_host_time = compute_target_host_time(info);
-    
     /* Now, let the host run while the guest is stopped to make the two
      * sync up. Note that this doesn't assume that guest time is stopped;
      * the offsetting in the next step will change add an offset to guest
      * time to account for the time paused even if the geust isn't 
      * usually paused in the VMM. */
     host_time = v3_get_host_time(time_state);
-    old_guest_time = v3_get_guest_time(time_state);
+    old_guest_time = v3_compute_guest_time(time_state, host_time);
+    target_host_time = compute_target_host_time(info, old_guest_time);
 
     while (target_host_time > host_time) {
        v3_yield(info);
        host_time = v3_get_host_time(time_state);
     }
 
-    guest_time = v3_get_guest_time(time_state);
+    guest_time = v3_compute_guest_time(time_state, host_time);
 
     /* We do *not* assume the guest timer was paused in the VM. If it was
      * this offseting is 0. If it wasn't, we need this. */
-    v3_offset_time(info, (sint64_t)old_guest_time - (sint64_t)guest_time);
+    v3_offset_time(info, (sint64_t)(old_guest_time - guest_time));
 
     return 0;
 }
@@ -177,12 +175,12 @@ static int skew_guest_time(struct guest_info * info) {
        if (time_state->enter_time) {
            /* Limit forward skew to 10% of the amount the guest has
             * run since we last could skew time */
-           max_skew = ((sint64_t)guest_time - (sint64_t)time_state->enter_time) / 10;
+           max_skew = (sint64_t)(guest_time - time_state->enter_time) / 10.0;
        } else {
            max_skew = 0;
        }
 
-       desired_skew = (sint64_t)target_guest_time - (sint64_t)guest_time;
+       desired_skew = (sint64_t)(target_guest_time - guest_time);
        skew = desired_skew > max_skew ? max_skew : desired_skew;
        PrintDebug("Guest %lld cycles behind where it should be.\n",
                   desired_skew);
@@ -194,11 +192,13 @@ static int skew_guest_time(struct guest_info * info) {
 
     return 0;
 }
+#endif /* V3_CONFIG_TIME_DILATION */
 
 // Control guest time in relation to host time so that the two stay 
 // appropriately synchronized to the extent possible. 
 int v3_adjust_time(struct guest_info * info) {
 
+#ifdef V3_CONFIG_TIME_DILATION
     /* First deal with yielding if we want to slow down the guest */
     yield_host_time(info);
 
@@ -206,7 +206,7 @@ int v3_adjust_time(struct guest_info * info) {
      * or because the VMM is doing something that takes a long time to emulate)
      * allow guest time to jump forward a bit */
     skew_guest_time(info);
-    
+#endif
     return 0;
 }
 
@@ -226,12 +226,24 @@ int
 v3_time_enter_vm( struct guest_info * info )
 {
     struct vm_time * time_state = &(info->time_state);
-    uint64_t guest_time, host_time;
+    uint64_t host_time;
 
     host_time = v3_get_host_time(time_state);
-    guest_time = v3_get_guest_time(time_state);
     time_state->enter_time = host_time;
-    time_state->guest_host_offset = (sint64_t)guest_time - (sint64_t)host_time;
+#ifdef V3_CONFIG_TIME_DILATION
+    { 
+        uint64_t guest_time;
+       sint64_t offset;
+        guest_time = v3_compute_guest_time(time_state, host_time);
+       // XXX we probably want to use an inline function to do these
+        // time differences to deal with sign and overflow carefully
+       offset = (sint64_t)guest_time - (sint64_t)host_time;
+       PrintDebug("v3_time_enter_vm: guest time offset %lld from host time.\n", offset);
+        time_state->guest_host_offset = offset;
+    }
+#else
+    time_state->guest_host_offset = 0;
+#endif
 
     return 0;
 }
@@ -265,11 +277,11 @@ int v3_remove_timer(struct guest_info * info, struct v3_timer * timer) {
 void v3_update_timers(struct guest_info * info) {
     struct vm_time *time_state = &info->time_state;
     struct v3_timer * tmp_timer;
-    uint64_t old_time = info->time_state.last_update;
     sint64_t cycles;
+    uint64_t old_time = info->time_state.last_update;
 
     time_state->last_update = v3_get_guest_time(time_state);
-    cycles = time_state->last_update - old_time;
+    cycles = (sint64_t)(time_state->last_update - old_time);
     V3_ASSERT(cycles >= 0);
 
     //    V3_Print("Updating timers with %lld elapsed cycles.\n", cycles);
index 5980dcb..343be38 100644 (file)
@@ -448,6 +448,15 @@ static int parse_operands(struct guest_info * core, uint8_t * instr_ptr,
 
            break;
        }
+       case INT: {
+           instr->dst_operand.type = IMM_OPERAND;
+           instr->dst_operand.size = operand_width;
+               instr->dst_operand.operand = *(uint8_t *)instr_ptr;
+           instr_ptr += operand_width;
+           instr->num_operands = 1;
+
+           break;
+       }
        case INVLPG: {
            uint8_t reg_code = 0;
 
@@ -505,7 +514,7 @@ static v3_op_type_t op_form_to_type(op_form_t form) {
        case INVLPG:
            return V3_OP_INVLPG;
 
-        case INT:
+       case INT:
            return V3_OP_INT;
            
        case MOV_CR2:
index bdfc8c0..73b5af9 100644 (file)
@@ -349,13 +349,6 @@ static int init_vmcs_bios(struct guest_info * core, struct vmx_data * vmx_state)
     
     // save STAR, LSTAR, FMASK, KERNEL_GS_BASE MSRs in MSR load/store area
     {
-#define IA32_STAR 0xc0000081
-#define IA32_LSTAR 0xc0000082
-#define IA32_FMASK 0xc0000084
-#define IA32_KERN_GS_BASE 0xc0000102
-
-#define IA32_CSTAR 0xc0000083 // Compatibility mode STAR (ignored for now... hopefully its not that important...)
-
        int msr_ret = 0;
 
        struct vmcs_msr_entry * exit_store_msrs = NULL;
@@ -387,24 +380,37 @@ static int init_vmcs_bios(struct guest_info * core, struct vmx_data * vmx_state)
        entry_load_msrs = (struct vmcs_msr_entry *)(vmx_state->msr_area + (sizeof(struct vmcs_msr_entry) * 8));
 
 
-       exit_store_msrs[0].index = IA32_STAR;
-       exit_store_msrs[1].index = IA32_LSTAR;
-       exit_store_msrs[2].index = IA32_FMASK;
-       exit_store_msrs[3].index = IA32_KERN_GS_BASE;
+       exit_store_msrs[0].index = IA32_STAR_MSR;
+       exit_store_msrs[1].index = IA32_LSTAR_MSR;
+       exit_store_msrs[2].index = IA32_FMASK_MSR;
+       exit_store_msrs[3].index = IA32_KERN_GS_BASE_MSR;
        
        memcpy(exit_store_msrs, exit_load_msrs, sizeof(struct vmcs_msr_entry) * 4);
        memcpy(exit_store_msrs, entry_load_msrs, sizeof(struct vmcs_msr_entry) * 4);
 
        
-       v3_get_msr(IA32_STAR, &(exit_load_msrs[0].hi), &(exit_load_msrs[0].lo));
-       v3_get_msr(IA32_LSTAR, &(exit_load_msrs[1].hi), &(exit_load_msrs[1].lo));
-       v3_get_msr(IA32_FMASK, &(exit_load_msrs[2].hi), &(exit_load_msrs[2].lo));
-       v3_get_msr(IA32_KERN_GS_BASE, &(exit_load_msrs[3].hi), &(exit_load_msrs[3].lo));
+       v3_get_msr(IA32_STAR_MSR, &(exit_load_msrs[0].hi), &(exit_load_msrs[0].lo));
+       v3_get_msr(IA32_LSTAR_MSR, &(exit_load_msrs[1].hi), &(exit_load_msrs[1].lo));
+       v3_get_msr(IA32_FMASK_MSR, &(exit_load_msrs[2].hi), &(exit_load_msrs[2].lo));
+       v3_get_msr(IA32_KERN_GS_BASE_MSR, &(exit_load_msrs[3].hi), &(exit_load_msrs[3].lo));
 
        msr_ret |= check_vmcs_write(VMCS_EXIT_MSR_STORE_ADDR, (addr_t)V3_PAddr(exit_store_msrs));
        msr_ret |= check_vmcs_write(VMCS_EXIT_MSR_LOAD_ADDR, (addr_t)V3_PAddr(exit_load_msrs));
        msr_ret |= check_vmcs_write(VMCS_ENTRY_MSR_LOAD_ADDR, (addr_t)V3_PAddr(entry_load_msrs));
 
+
+       v3_hook_msr(core->vm_info, IA32_STAR_MSR, NULL, NULL, NULL);
+       v3_hook_msr(core->vm_info, IA32_LSTAR_MSR, NULL, NULL, NULL);
+       v3_hook_msr(core->vm_info, IA32_FMASK_MSR, NULL, NULL, NULL);
+       v3_hook_msr(core->vm_info, IA32_KERN_GS_BASE_MSR, NULL, NULL, NULL);
+
+
+       // IMPORTANT: These SYSCALL MSRs are currently not handled by hardware or cached
+       // We should really emulate these ourselves, or ideally include them in the MSR store area if there is room
+       v3_hook_msr(core->vm_info, IA32_CSTAR_MSR, NULL, NULL, NULL);
+       v3_hook_msr(core->vm_info, SYSENTER_CS_MSR, NULL, NULL, NULL);
+       v3_hook_msr(core->vm_info, SYSENTER_ESP_MSR, NULL, NULL, NULL);
+       v3_hook_msr(core->vm_info, SYSENTER_EIP_MSR, NULL, NULL, NULL);
     }    
 
     /* Sanity check ctrl/reg fields against hw_defaults */
@@ -750,7 +756,7 @@ static void print_exit_log(struct guest_info * info) {
  */
 int v3_vmx_enter(struct guest_info * info) {
     int ret = 0;
-    //uint32_t tsc_offset_low, tsc_offset_high;
+    uint32_t tsc_offset_low, tsc_offset_high;
     struct vmx_exit_info exit_info;
     struct vmx_data * vmx_info = (struct vmx_data *)(info->vmm_data);
 
@@ -795,10 +801,10 @@ int v3_vmx_enter(struct guest_info * info) {
     // Perform last-minute time bookkeeping prior to entering the VM
     v3_time_enter_vm(info);
 
-    // tsc_offset_high = (uint32_t)((v3_tsc_host_offset(&info->time_state) >> 32) & 0xffffffff);
-    // tsc_offset_low = (uint32_t)(v3_tsc_host_offset(&info->time_state) & 0xffffffff);
-    // check_vmcs_write(VMCS_TSC_OFFSET_HIGH, tsc_offset_high);
-    // check_vmcs_write(VMCS_TSC_OFFSET, tsc_offset_low);
+    tsc_offset_high = (uint32_t)((v3_tsc_host_offset(&info->time_state) >> 32) & 0xffffffff);
+    tsc_offset_low = (uint32_t)(v3_tsc_host_offset(&info->time_state) & 0xffffffff);
+    check_vmcs_write(VMCS_TSC_OFFSET_HIGH, tsc_offset_high);
+    check_vmcs_write(VMCS_TSC_OFFSET, tsc_offset_low);
 
     if (v3_update_vmcs_host_state(info)) {
        v3_enable_ints();
index d69787a..9b02a0a 100644 (file)
@@ -50,7 +50,7 @@ int v3_init_vmx_io_map(struct v3_vm_info * vm) {
     vm->io_map.update_map = update_map;
     
     vm->io_map.arch_data = V3_VAddr(V3_AllocPages(2));
-    memset(vm->io_map.arch_data, 0, PAGE_SIZE_4KB * 2);
+    memset(vm->io_map.arch_data, 0xff, PAGE_SIZE_4KB * 2);
 
     v3_refresh_io_map(vm);
 
@@ -68,23 +68,25 @@ int v3_handle_vmx_io_in(struct guest_info * core, struct vmx_exit_info * exit_in
     struct v3_io_hook * hook = NULL;
     int read_size = 0;
 
-
     hook = v3_get_io_hook(core->vm_info, io_qual.port);
 
-    if (hook == NULL) {
-        PrintError("Hook not present for IN on port %x\n", io_qual.port);
-        return -1;
-    }
-
     read_size = io_qual.access_size + 1;
 
     PrintDebug("IN of %d bytes on port %d (0x%x)\n", read_size, io_qual.port, io_qual.port);
 
-    if (hook->read(core, io_qual.port, &(core->vm_regs.rax), read_size, hook->priv_data) != read_size) {
-        PrintError("Read failure for IN on port %x\n", io_qual.port);
-        return -1;
-    }
+    if (hook == NULL) {
+       PrintDebug("IN operation on unhooked IO port 0x%x\n", io_qual.port);
 
+       /* What are the HW semantics for an IN on an invalid port? 
+        *  Do we need to clear the register value or leave it untouched??? 
+        */
+    } else {
+       if (hook->read(core, io_qual.port, &(core->vm_regs.rax), read_size, hook->priv_data) != read_size) {
+           PrintError("Read failure for IN on port %x\n", io_qual.port);
+           return -1;
+       }
+    }
+    
 
     core->rip += exit_info->instr_len;
 
@@ -103,10 +105,6 @@ int v3_handle_vmx_io_ins(struct guest_info * core, struct vmx_exit_info * exit_i
 
     hook = v3_get_io_hook(core->vm_info, io_qual.port);
 
-    if (hook == NULL) {
-        PrintError("Hook not present for INS on port 0x%x\n", io_qual.port);
-        return -1;
-    }
 
     PrintDebug("INS on port 0x%x\n", io_qual.port);
 
@@ -143,10 +141,20 @@ int v3_handle_vmx_io_ins(struct guest_info * core, struct vmx_exit_info * exit_i
     }
 
     do {
-        if (hook->read(core, io_qual.port, (char *)host_addr, read_size, hook->priv_data) != read_size) {
-            PrintError("Read Failure for INS on port 0x%x\n", io_qual.port);
-            return -1;
-        }
+
+       if (hook == NULL) {
+           PrintDebug("INS operation on unhooked IO port 0x%x\n", io_qual.port);
+           
+            /* What are the HW semantics for an INS on an invalid port? 
+            *  Do we need to clear the memory region or leave it untouched??? 
+            */     
+       } else {
+           if (hook->read(core, io_qual.port, (char *)host_addr, read_size, hook->priv_data) != read_size) {
+               PrintError("Read Failure for INS on port 0x%x\n", io_qual.port);
+               return -1;
+           }
+       }
+       
 
         host_addr += rdi_change;
         core->vm_regs.rdi += rdi_change;
@@ -172,22 +180,20 @@ int v3_handle_vmx_io_out(struct guest_info * core, struct vmx_exit_info * exit_i
 
     hook =  v3_get_io_hook(core->vm_info, io_qual.port);
 
-    if (hook == NULL) {
-        PrintError("Hook not present for out on port %x\n", io_qual.port);
-        return -1;
-    }
 
     write_size = io_qual.access_size + 1;
     
     PrintDebug("OUT of %d bytes on port %d (0x%x)\n", write_size, io_qual.port, io_qual.port);
 
-    if (hook->write(core, io_qual.port, &(core->vm_regs.rax), write_size, hook->priv_data) != write_size) {
-        PrintError("Write failure for out on port %x\n",io_qual.port);
-        return -1;
+    if (hook == NULL) {
+       PrintDebug("OUT operation on unhooked IO port 0x%x\n", io_qual.port);
+    } else {  
+       if (hook->write(core, io_qual.port, &(core->vm_regs.rax), write_size, hook->priv_data) != write_size) {
+           PrintError("Write failure for out on port %x\n",io_qual.port);
+           return -1;
+       }
     }
 
-
-
     core->rip += exit_info->instr_len;
 
     return 0;
@@ -207,11 +213,6 @@ int v3_handle_vmx_io_outs(struct guest_info * core, struct vmx_exit_info * exit_
 
     hook = v3_get_io_hook(core->vm_info, io_qual.port);
 
-    if (hook == NULL) {
-        PrintError("Hook not present for OUTS on port 0x%x\n", io_qual.port);
-        return -1;
-    }
-
     PrintDebug("OUTS on port 0x%x\n", io_qual.port);
 
     write_size = io_qual.access_size + 1;
@@ -248,10 +249,16 @@ int v3_handle_vmx_io_outs(struct guest_info * core, struct vmx_exit_info * exit_
     }
 
     do {
-       if (hook->write(core, io_qual.port, (char *)host_addr, write_size, hook->priv_data) != write_size) {
-           PrintError("Read failure for INS on port 0x%x\n", io_qual.port);
-           return -1;
-       }
+
+       if (hook == NULL) {
+           PrintDebug("OUTS operation on unhooked IO port 0x%x\n", io_qual.port);
+       } else {
+           if (hook->write(core, io_qual.port, (char *)host_addr, write_size, hook->priv_data) != write_size) {
+               PrintError("Read failure for INS on port 0x%x\n", io_qual.port);
+               return -1;
+           }
+       }
+       
 
        host_addr += rsi_change;
        core->vm_regs.rsi += rsi_change;
index e1ba86f..f470c37 100644 (file)
@@ -66,7 +66,7 @@ int v3_init_vmx_msr_map(struct v3_vm_info * vm) {
     msr_map->update_map = update_map;
     
     msr_map->arch_data = V3_VAddr(V3_AllocPages(1));
-    memset(msr_map->arch_data, 0, PAGE_SIZE_4KB);
+    memset(msr_map->arch_data, 0xff, PAGE_SIZE_4KB);
     
     v3_refresh_msr_map(vm);
     
index 4669029..807708e 100644 (file)
@@ -53,7 +53,7 @@ struct vnet_dev {
        
     void * private_data;
 
-    struct list_head node;\r
+    struct list_head node;
 } __attribute__((packed));
 
 
@@ -303,7 +303,7 @@ void v3_vnet_del_route(uint32_t route_idx){
     flags = vnet_lock_irqsave(vnet_state.lock);
 
     list_for_each_entry(route, &(vnet_state.routes), node) {
-       V3_Print("v3_vnet_del_route, route idx: %d\n", route->idx);
+       Vnet_Print(0, "v3_vnet_del_route, route idx: %d\n", route->idx);
        if(route->idx == route_idx){
            list_del(&(route->node));
            Vnet_Free(route);
@@ -549,7 +549,7 @@ int v3_vnet_send_pkt(struct v3_vnet_pkt * pkt, void * private_data) {
 
 
 int v3_vnet_add_dev(struct v3_vm_info * vm, uint8_t * mac, 
-                   struct v3_vnet_dev_ops *ops, int quote, int poll_state,
+                   struct v3_vnet_dev_ops * ops, int quote, int poll_state,
                    void * priv_data){
     struct vnet_dev * new_dev = NULL;
     unsigned long flags;
@@ -563,6 +563,7 @@ int v3_vnet_add_dev(struct v3_vm_info * vm, uint8_t * mac,
    
     memcpy(new_dev->mac_addr, mac, 6);
     new_dev->dev_ops.input = ops->input;
+    new_dev->dev_ops.poll = ops->poll;
     new_dev->private_data = priv_data;
     new_dev->vm = vm;
     new_dev->dev_id = 0;
@@ -575,6 +576,12 @@ int v3_vnet_add_dev(struct v3_vm_info * vm, uint8_t * mac,
        list_add(&(new_dev->node), &(vnet_state.devs));
        new_dev->dev_id = ++ vnet_state.dev_idx;
        vnet_state.num_devs ++;
+
+       if(new_dev->poll) {
+           v3_enqueue(vnet_state.poll_devs, (addr_t)new_dev);
+       }
+    } else {
+       PrintError("VNET/P: Device with the same MAC is already there\n");
     }
 
     vnet_unlock_irqrestore(vnet_state.lock, flags);
@@ -708,25 +715,23 @@ void v3_vnet_del_bridge(uint8_t type) {
   * that runs on multiple cores 
   * or it could be running on a dedicated side core
   */
-static int vnet_tx_flush(void *args){
+static int vnet_tx_flush(void * args){
     struct vnet_dev * dev = NULL;
     int ret;
 
     Vnet_Print(0, "VNET/P Polling Thread Starting ....\n");
 
-    /* we need thread sleep/wakeup in Palacios */
     while(!vnet_thread_should_stop()){
        dev = (struct vnet_dev *)v3_dequeue(vnet_state.poll_devs);
        if(dev != NULL){
            if(dev->poll && dev->dev_ops.poll != NULL){
                ret = dev->dev_ops.poll(dev->vm, dev->quote, dev->private_data);
-
+               
                if (ret < 0){
-                   PrintDebug("VNET/P: poll from device %p error!\n", dev);
+                   Vnet_Print(0, "VNET/P: poll from device %p error!\n", dev);
                }
-
-               v3_enqueue(vnet_state.poll_devs, (addr_t)dev); 
            }
+           v3_enqueue(vnet_state.poll_devs, (addr_t)dev); 
        }else { /* no device needs to be polled */
           /* sleep here? */
            Vnet_Yield();
@@ -736,7 +741,6 @@ static int vnet_tx_flush(void *args){
     return 0;
 }
 
-
 int v3_init_vnet() {
     memset(&vnet_state, 0, sizeof(vnet_state));
        
@@ -758,7 +762,7 @@ int v3_init_vnet() {
 
     vnet_state.poll_devs = v3_create_queue();
 
-    vnet_state.pkt_flush_thread = vnet_start_thread(vnet_tx_flush, NULL, "vnetd");
+    vnet_state.pkt_flush_thread = vnet_start_thread(vnet_tx_flush, NULL, "vnetd-1");
 
     Vnet_Debug("VNET/P is initiated\n");
 
index e3b6bca..1d44067 100644 (file)
                <device class="8254_PIT" id="PIT" />
                <device class="BOCHS_DEBUG" id="bochs debug"/>
                <device class="OS_DEBUG" id="os debug" />
-
-
-<!--
                <device class="LAPIC" id="apic"/>
                <device class="IOAPIC" id="ioapic">
                        <apic>apic</apic>
                </device>
--->
 <!--
                <device class="CGA_VIDEO" id="cga" passthrough="enable" />
                <device class="TELNET_CONSOLE" id="telnet console">