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 ssh://palacios@newskysaw/home/palacios/palacios into devel
Jack Lange [Wed, 2 Mar 2011 22:21:39 +0000 (16:21 -0600)]
Conflicts:

palacios/src/devices/apic.c

13 files changed:
Kconfig
palacios/include/palacios/vm_guest.h
palacios/include/palacios/vmm_extensions.h [new file with mode: 0644]
palacios/include/palacios/vmm_mtrr.h [new file with mode: 0644]
palacios/src/devices/apic.c
palacios/src/palacios/Makefile
palacios/src/palacios/svm.c
palacios/src/palacios/vmm.c
palacios/src/palacios/vmm_config.c
palacios/src/palacios/vmm_extensions.c [new file with mode: 0644]
palacios/src/palacios/vmm_mtrr.c [new file with mode: 0644]
palacios/src/palacios/vmm_symbiotic.c
palacios/src/palacios/vmm_time.c

diff --git a/Kconfig b/Kconfig
index 45a0568..06f962b 100644 (file)
--- a/Kconfig
+++ b/Kconfig
@@ -225,10 +225,16 @@ endmenu
 
 
 menu "Time Management"
-
+config VIRTUALIZE_TIME
+       bool "Enable Time virtualization"
+       default n
+       help
+          Enables the timer virtualization extensions
 config TIME_HIDE_VM_COST
         bool "Hide VMM Run Cost"
        default n
+       depends on VIRTUALIZE_TIME
        help
            Offset guest time from host time sufficiently to hide the cost of
            running in the virtual machine. This can aid the consistency of
@@ -238,6 +244,7 @@ config TIME_HIDE_VM_COST
 config TIME_VIRTUALIZE_TSC
        bool "Fully virtualize guest TSC"
        default n
+       depends on VIRTUALIZE_TIME
        help
            Virtualize the processor time stamp counter in the guest, 
            generally increasing consistency between various time sources 
index 8e91634..078bbb9 100644 (file)
@@ -125,9 +125,7 @@ struct guest_info {
 
     /* the logical cpu on which this core runs */
     uint32_t cpu_id;
-    /* the physical cpu on which this core runs */
-    uint32_t host_cpu_id;
-       
+     
 };
 
 
diff --git a/palacios/include/palacios/vmm_extensions.h b/palacios/include/palacios/vmm_extensions.h
new file mode 100644 (file)
index 0000000..c6a2ae2
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National 
+ * Science Foundation and the Department of Energy.  
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico.  You can find out more at 
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
+ * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
+ * All rights reserved.
+ *
+ * Author: Jack Lange <jarusl@cs.northwestern.edu>
+ *
+ * This is free software.  You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#ifndef __VMM_EXTENSIONS_H__
+#define __VMM_EXTENSIONS_H__
+
+#ifdef __V3VEE__
+
+#include <palacios/vmm.h>
+#include <palacios/vmm_list.h>
+#include <palacios/vm_guest.h>
+
+struct v3_extension_impl {
+    char * name;
+    int (*init)(struct v3_vm_info * vm, v3_cfg_tree_t * cfg);
+    int (*deinit)(struct v3_vm_info * vm, void * priv_data);
+    int (*core_init)(struct guest_info * core);
+    int (*core_deinit)(struct guest_info * core);
+};
+
+
+
+struct v3_extension {
+    struct v3_extension_impl * impl;
+    void * priv_data;
+
+    struct list_head node;
+};
+
+
+
+int V3_init_extensions();
+int V3_deinit_extensions();
+
+
+
+#define register_extension(ext)                                        \
+    static struct v3_extension_impl * _v3_ext                  \
+    __attribute__((used))                                      \
+       __attribute__((unused, __section__("_v3_extensions"),   \
+                      aligned(sizeof(addr_t))))                \
+       = ext;
+
+
+
+#endif
+
+#endif
diff --git a/palacios/include/palacios/vmm_mtrr.h b/palacios/include/palacios/vmm_mtrr.h
new file mode 100644 (file)
index 0000000..0901781
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National 
+ * Science Foundation and the Department of Energy.  
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico.  You can find out more at 
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2011, Jack Lange <jarusl@cs.northwestern.edu> 
+ * Copyright (c) 2011, The V3VEE Project <http://www.v3vee.org> 
+ * All rights reserved.
+ *
+ * Author: Jack Lange <jarusl@cs.northwestern.edu>
+ *
+ * This is free software.  You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#ifndef __VMM_MTRR_H__
+#define __VMM_MTRR_H__
+
+
+#ifdef __V3VEE__
+
+#include <palacios/vmm.h>
+
+
+
+#endif
+
+#endif
index 427ec79..dab92b6 100644 (file)
 #ifndef CONFIG_DEBUG_APIC
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
-#endif
-
+#else
 
-#ifdef CONFIG_DEBUG_APIC
 static char * shorthand_str[] = { 
     "(no shorthand)",
     "(self)",
@@ -54,12 +52,8 @@ static char * deliverymode_str[] = {
     "(Start Up)",
     "(ExtInt)",
 };
-#endif
-
-// Temporary removal of locking
-#define v3_lock(p) p=p
-#define v3_unlock(p) p=p
 
+#endif
 
 typedef enum { APIC_TMR_INT, APIC_THERM_INT, APIC_PERF_INT, 
               APIC_LINT0_INT, APIC_LINT1_INT, APIC_ERR_INT } apic_irq_type_t;
@@ -233,10 +227,7 @@ struct apic_state {
 
     uint32_t eoi;
 
-    v3_lock_t  lock;
 
-    // debug
-    uint8_t in_icr;   
 };
 
 
@@ -244,8 +235,7 @@ struct apic_state {
 
 struct apic_dev_state {
     int num_apics;
-    //    v3_lock_t ipi_lock;   // acquired by route_ipi - only one IPI active at a time
-
+  
     struct apic_state apics[0];
 } __attribute__((packed));
 
@@ -313,28 +303,25 @@ static void init_apic_state(struct apic_state * apic, uint32_t id) {
     apic->ext_apic_ctrl.val = 0x00000000;
     apic->spec_eoi.val = 0x00000000;
 
-    v3_lock_init(&(apic->lock));
 
-    //debug
-    apic->in_icr=0;
 }
 
 
 
 
-// MSR handler - locks apic itself
+
 static int read_apic_msr(struct guest_info * core, uint_t msr, v3_msr_t * dst, void * priv_data) {
     struct apic_dev_state * apic_dev = (struct apic_dev_state *)priv_data;
     struct apic_state * apic = &(apic_dev->apics[core->cpu_id]);
 
     PrintDebug("apic %u: core %u: MSR read\n", apic->lapic_id.val, core->cpu_id);
-    v3_lock(apic->lock);
+
     dst->value = apic->base_addr;
-    v3_unlock(apic->lock);
+
     return 0;
 }
 
-// MSR handler - locks apic itself
+
 static int write_apic_msr(struct guest_info * core, uint_t msr, v3_msr_t src, void * priv_data) {
     struct apic_dev_state * apic_dev = (struct apic_dev_state *)priv_data;
     struct apic_state * apic = &(apic_dev->apics[core->cpu_id]);
@@ -350,7 +337,7 @@ static int write_apic_msr(struct guest_info * core, uint_t msr, v3_msr_t src, vo
        return -1;
     }
     
-    v3_lock(apic->lock);
+
 
     v3_delete_mem_region(core->vm_info, old_reg);
 
@@ -361,11 +348,11 @@ static int write_apic_msr(struct guest_info * core, uint_t msr, v3_msr_t src, vo
                         apic_read, apic_write, apic_dev) == -1) {
        PrintError("apic %u: core %u: Could not hook new APIC Base address\n",
                   apic->lapic_id.val, core->cpu_id);
-       v3_unlock(apic->lock);
+
        return -1;
     }
 
-    v3_unlock(apic->lock);
+
     return 0;
 }
 
@@ -375,8 +362,7 @@ static int write_apic_msr(struct guest_info * core, uint_t msr, v3_msr_t src, vo
 //    -1 = error
 //     0 = OK, no interrupt needed now
 //     1 = OK, interrupt needed now
-// the caller is expeced to have locked the apic
-static int activate_apic_irq_nolock(struct apic_state * apic, uint32_t irq_num) {
+static int activate_apic_irq(struct apic_state * apic, uint32_t irq_num) {
     int major_offset = (irq_num & ~0x00000007) >> 3;
     int minor_offset = irq_num & 0x00000007;
     uint8_t * req_location = apic->int_req_reg + major_offset;
@@ -400,23 +386,17 @@ static int activate_apic_irq_nolock(struct apic_state * apic, uint32_t irq_num)
 
     if (*en_location & flag) {
        *req_location |= flag;
-
-       if (apic->in_icr) { 
-           PrintError("apic %u: core %d: activate_apic_irq_nolock to deliver irq 0x%x when in_icr=1\n",  apic->lapic_id.val, apic->core->cpu_id, irq_num);
-           //      return 0;
-       }
-
        return 1;
     } else {
        PrintDebug("apic %u: core %d: Interrupt  not enabled... %.2x\n", 
                   apic->lapic_id.val, apic->core->cpu_id,*en_location);
-       return 0;
     }
 
+    return 0;
 }
 
 
-// Caller is expected to have locked the apic
+
 static int get_highest_isr(struct apic_state * apic) {
     int i = 0, j = 0;
 
@@ -438,7 +418,7 @@ static int get_highest_isr(struct apic_state * apic) {
 }
  
 
-// Caller is expected to have locked the apic
+
 static int get_highest_irr(struct apic_state * apic) {
     int i = 0, j = 0;
 
@@ -461,7 +441,7 @@ static int get_highest_irr(struct apic_state * apic) {
  
 
 
-// Caller is expected to have locked the apic
+
 static int apic_do_eoi(struct apic_state * apic) {
     int isr_irq = get_highest_isr(apic);
 
@@ -493,8 +473,8 @@ static int apic_do_eoi(struct apic_state * apic) {
     return 0;
 }
  
-// Caller is expected to have locked the apic
-static int activate_internal_irq_nolock(struct apic_state * apic, apic_irq_type_t int_type) {
+
+static int activate_internal_irq(struct apic_state * apic, apic_irq_type_t int_type) {
     uint32_t vec_num = 0;
     uint32_t del_mode = 0;
     int masked = 0;
@@ -544,7 +524,7 @@ static int activate_internal_irq_nolock(struct apic_state * apic, apic_irq_type_
 
     if (del_mode == APIC_FIXED_DELIVERY) {
        //PrintDebug("Activating internal APIC IRQ %d\n", vec_num);
-       return activate_apic_irq_nolock(apic, vec_num);
+       return activate_apic_irq(apic, vec_num);
     } else {
        PrintError("apic %u: core ?: Unhandled Delivery Mode\n", apic->lapic_id.val);
        return -1;
@@ -552,7 +532,7 @@ static int activate_internal_irq_nolock(struct apic_state * apic, apic_irq_type_
 }
 
 
-// Caller is expected to have locked the destination apic
+
 static inline int should_deliver_cluster_ipi(struct guest_info * dst_core, 
                                             struct apic_state * dst_apic, uint8_t mda) {
 
@@ -572,7 +552,6 @@ static inline int should_deliver_cluster_ipi(struct guest_info * dst_core,
     }
 }
 
-// Caller is expected to have locked the destiation apic
 static inline int should_deliver_flat_ipi(struct guest_info * dst_core,
                                          struct apic_state * dst_apic, uint8_t mda) {
 
@@ -594,7 +573,7 @@ static inline int should_deliver_flat_ipi(struct guest_info * dst_core,
 }
 
 
-// Caller is expected to have locked the destiation apic
+
 static int should_deliver_ipi(struct guest_info * dst_core, 
                              struct apic_state * dst_apic, uint8_t mda) {
 
@@ -624,7 +603,7 @@ static int should_deliver_ipi(struct guest_info * dst_core,
     }
 }
 
-// Caller is expected to have locked the destination apic
+
 // Only the src_apic pointer is used
 static int deliver_ipi(struct apic_state * src_apic, 
                       struct apic_state * dst_apic, 
@@ -632,20 +611,22 @@ static int deliver_ipi(struct apic_state * src_apic,
 
 
     struct guest_info * dst_core = dst_apic->core;
-    int do_xcall;
+
 
     switch (del_mode) {
 
        case APIC_FIXED_DELIVERY:  
-       case APIC_LOWEST_DELIVERY:
+       case APIC_LOWEST_DELIVERY: {
            // lowest priority - 
            // caller needs to have decided which apic to deliver to!
 
+           int do_xcall;
+
            PrintDebug("delivering IRQ %d to core %u\n", vector, dst_core->cpu_id); 
 
-           do_xcall=activate_apic_irq_nolock(dst_apic, vector);
+           do_xcall = activate_apic_irq(dst_apic, vector);
            
-           if (do_xcall<0) { 
+           if (do_xcall < 0) { 
                PrintError("Failed to activate apic irq!\n");
                return -1;
            }
@@ -666,7 +647,7 @@ static int deliver_ipi(struct apic_state * src_apic,
            }
 
            break;
-
+       }
        case APIC_INIT_DELIVERY: { 
 
            PrintDebug(" INIT delivery to core %u\n", dst_core->cpu_id);
@@ -766,28 +747,13 @@ static struct apic_state * find_physical_apic(struct apic_dev_state *apic_dev, s
 
 }
 
-// route_ipi is responsible for all locking
-// the assumption is that you enter with no locks
-// there is a global lock for the icc bus, so only
-// one route_ipi progresses at any time
-// destination apics are locked as needed
-// if multiple apic locks are acquired at any point,
-// this is done in the order of the array, so no
-// deadlock should be possible
+
 static int route_ipi(struct apic_dev_state * apic_dev,
                     struct apic_state * src_apic, 
                     struct int_cmd_reg * icr) {
     struct apic_state * dest_apic = NULL;
 
 
-    //v3_lock(apic_dev->ipi_lock);  // this may not be needed
-    // now I know only one IPI is being routed, this one
-    // also, I do not have any apic locks
-    // I need to acquire locks on pairs of src/dest apics
-    // and I will do that using the total order
-    // given by their cores
-
-
     PrintDebug("apic: IPI %s %u from apic %p to %s %s %u (icr=0x%llx)\n",
               deliverymode_str[icr->del_mode], 
               icr->vec, 
@@ -797,20 +763,6 @@ static int route_ipi(struct apic_dev_state * apic_dev,
               icr->dst,
               icr->val);
 
-#if 0
-        if (icr->vec!=48) { 
-           V3_Print("apic: IPI %s %u from apic %p to %s %s %u (icr=0x%llx)\n",
-                   deliverymode_str[icr->del_mode], 
-                   icr->vec, 
-                   src_apic,          
-                   (icr->dst_mode == 0) ? "(physical)" : "(logical)", 
-                   shorthand_str[icr->dst_shorthand], 
-                   icr->dst,
-                   icr->val);
-       }
-
-#endif
-
 
     switch (icr->dst_shorthand) {
 
@@ -821,25 +773,23 @@ static int route_ipi(struct apic_dev_state * apic_dev,
                
                if (dest_apic==NULL) { 
                    PrintError("apic: Attempted send to unregistered apic id=%u\n", icr->dst);
-                   goto route_ipi_out_bad;
+                   return -1;
                }
 
 
-       
-               //V3_Print("apic: phsyical destination of %u (apic %u at 0x%p)\n", icr->dst,dest_apic->lapic_id.val,dest_apic);
+               dest_apic =  &(apic_dev->apics[icr->dst]);
+               
 
-               v3_lock(dest_apic->lock);
 
                if (deliver_ipi(src_apic, dest_apic, 
                                icr->vec, icr->del_mode) == -1) {
                    PrintError("apic: Could not deliver IPI\n");
-                   v3_unlock(dest_apic->lock);
-                   goto route_ipi_out_bad;
+                   return -1;
                }
 
-               v3_unlock(dest_apic->lock);
 
-               //V3_Print("apic: done\n");
+               V3_Print("apic: done\n");
+
 
            } else if (icr->dst_mode == APIC_DEST_LOGICAL) {
                
@@ -855,89 +805,56 @@ static int route_ipi(struct apic_dev_state * apic_dev,
                        
                        dest_apic = &(apic_dev->apics[i]);
                        
-                       v3_lock(dest_apic->lock);
-                       
                        int del_flag = should_deliver_ipi(dest_apic->core, dest_apic, mda);
                        
                        if (del_flag == -1) {
                            PrintError("apic: Error checking delivery mode\n");
-                           v3_unlock(dest_apic->lock);
-                           goto route_ipi_out_bad;
+                           return -1;
                        } else if (del_flag == 1) {
                            if (deliver_ipi(src_apic, dest_apic, 
                                            icr->vec, icr->del_mode) == -1) {
                                PrintError("apic: Error: Could not deliver IPI\n");
-                               v3_unlock(dest_apic->lock);
-                               goto route_ipi_out_bad;
+                               return -1;
                            }
                        }
-                       
-                       v3_unlock(dest_apic->lock);
                    }
                } else {  //APIC_LOWEST_DELIVERY
                    // logical, lowest priority
-                   // scan, keeping a lock on the current best, then trigger
                    int i;
-                   int have_cur_lock;
                    struct apic_state * cur_best_apic = NULL;
-                   
                    uint8_t mda = icr->dst;
-                   
-                   have_cur_lock=0;
-
-
-                   // Note that even if there are multiple concurrent 
-                   // copies of this loop executing, they are all 
-                   // locking in the same order
-
+                  
                    for (i = 0; i < apic_dev->num_apics; i++) { 
-                       
+                       int del_flag = 0;
+
                        dest_apic = &(apic_dev->apics[i]);
                        
-                       v3_lock(dest_apic->lock);
-                       have_cur_lock=1;
-                       
-                       int del_flag = should_deliver_ipi(dest_apic->core, dest_apic, mda);
+                       del_flag = should_deliver_ipi(dest_apic->core, dest_apic, mda);
                        
                        if (del_flag == -1) {
                            PrintError("apic: Error checking delivery mode\n");
-                           v3_unlock(dest_apic->lock);
-                           if (cur_best_apic && cur_best_apic!=dest_apic) { 
-                               v3_unlock(cur_best_apic->lock);
-                           }
-                           goto route_ipi_out_bad;
+
+                           return -1;
                        } else if (del_flag == 1) {
                            // update priority for lowest priority scan
                            if (!cur_best_apic) {
-                               cur_best_apic=dest_apic;  // note we leave it locked
-                               have_cur_lock=0;          // we will unlock as cur_best_apic
+                               cur_best_apic = dest_apic;  
                            } else if (dest_apic->task_prio.val < cur_best_apic->task_prio.val) {
-                               // we now unlock the current best one and then switch
-                               // so in the end we have a lock on the new cur_best_apic
-                               v3_unlock(cur_best_apic->lock);
-                               cur_best_apic=dest_apic;
-                               have_cur_lock=0; // will unlock as cur_best_apic
+                               cur_best_apic = dest_apic;
                            } 
-                       }
-                       if (have_cur_lock) {
-                           v3_unlock(dest_apic->lock);
-                       }
-                       
+                       }                       
                    }
+
                    // now we will deliver to the best one if it exists
-                   // and it is locked
                    if (!cur_best_apic) { 
                        PrintDebug("apic: lowest priority deliver, but no destinations!\n");
                    } else {
                        if (deliver_ipi(src_apic, cur_best_apic, 
                                        icr->vec, icr->del_mode) == -1) {
                            PrintError("apic: Error: Could not deliver IPI\n");
-                           v3_unlock(cur_best_apic->lock);
-                           goto route_ipi_out_bad;
-                       } else {
-                           v3_unlock(cur_best_apic->lock);
+                           return -1;
                        }
-                           //V3_Print("apic: logical, lowest priority delivery to apic %u\n",cur_best_apic->lapic_id.val);
+                       //V3_Print("apic: logical, lowest priority delivery to apic %u\n",cur_best_apic->lapic_id.val);
                    }
                }
            }
@@ -946,69 +863,53 @@ static int route_ipi(struct apic_dev_state * apic_dev,
            
        case APIC_SHORTHAND_SELF:  // self
 
-           /* I assume I am already locked! */
-
            if (src_apic == NULL) {    /* this is not an apic, but it's trying to send to itself??? */
                PrintError("apic: Sending IPI to self from generic IPI sender\n");
                break;
            }
 
-           v3_lock(src_apic->lock);
+
 
            if (icr->dst_mode == APIC_DEST_PHYSICAL)  {  /* physical delivery */
                if (deliver_ipi(src_apic, src_apic, icr->vec, icr->del_mode) == -1) {
                    PrintError("apic: Could not deliver IPI to self (physical)\n");
-                   v3_unlock(src_apic->lock);
-                   goto route_ipi_out_bad;
+                   return -1;
                }
            } else if (icr->dst_mode == APIC_DEST_LOGICAL) {  /* logical delivery */
                PrintError("apic: use of logical delivery in self (untested)\n");
                if (deliver_ipi(src_apic, src_apic, icr->vec, icr->del_mode) == -1) {
                    PrintError("apic: Could not deliver IPI to self (logical)\n");
-                   v3_unlock(src_apic->lock);
-                   goto route_ipi_out_bad;
+                   return -1;
                }
            }
-           v3_unlock(src_apic->lock);
+
            break;
            
        case APIC_SHORTHAND_ALL: 
        case APIC_SHORTHAND_ALL_BUT_ME: { /* all and all-but-me */
            /* assuming that logical verus physical doesn't matter
               although it is odd that both are used */
-
            int i;
 
            for (i = 0; i < apic_dev->num_apics; i++) { 
                dest_apic = &(apic_dev->apics[i]);
                
-               
                if ((dest_apic != src_apic) || (icr->dst_shorthand == APIC_SHORTHAND_ALL)) { 
-                   v3_lock(dest_apic->lock);
                    if (deliver_ipi(src_apic, dest_apic, icr->vec, icr->del_mode) == -1) {
                        PrintError("apic: Error: Could not deliver IPI\n");
-                       v3_unlock(dest_apic->lock);
-                       goto route_ipi_out_bad;
+                       return -1;
                    }
-                   v3_unlock(dest_apic->lock);
                }
-               
            }
-       }
+
            break;
+       }
        default:
            PrintError("apic: Error routing IPI, invalid Mode (%d)\n", icr->dst_shorthand);
-           goto route_ipi_out_bad;
+           return -1;
     }
-
-
-    // route_ipi_out_good:
-    //v3_unlock(apic_dev->ipi_lock);  
     return 0;
-
- route_ipi_out_bad:
-    //v3_unlock(apic_dev->ipi_lock);  
-    return -1;
 }
 
 
@@ -1020,7 +921,6 @@ static int apic_read(struct guest_info * core, addr_t guest_addr, void * dst, ui
     struct apic_msr * msr = (struct apic_msr *)&(apic->base_addr_msr.value);
     uint32_t val = 0;
 
-    v3_lock(apic->lock);
 
     PrintDebug("apic %u: core %u: at %p: Read apic address space (%p)\n",
               apic->lapic_id.val, core->cpu_id, apic, (void *)guest_addr);
@@ -1028,8 +928,7 @@ static int apic_read(struct guest_info * core, addr_t guest_addr, void * dst, ui
     if (msr->apic_enable == 0) {
        PrintError("apic %u: core %u: Read from APIC address space with disabled APIC, apic msr=0x%llx\n",
                   apic->lapic_id.val, core->cpu_id, apic->base_addr_msr.value);
-
-       goto apic_read_out_bad;
+       return -1;
     }
 
 
@@ -1242,7 +1141,7 @@ static int apic_read(struct guest_info * core, addr_t guest_addr, void * dst, ui
        default:
            PrintError("apic %u: core %u: Read from Unhandled APIC Register: %x (getting zero)\n", 
                       apic->lapic_id.val, core->cpu_id, (uint32_t)reg_addr);
-           goto apic_read_out_bad;
+           return -1;
     }
 
 
@@ -1265,20 +1164,13 @@ static int apic_read(struct guest_info * core, addr_t guest_addr, void * dst, ui
     } else {
        PrintError("apic %u: core %u: Invalid apic read length (%d)\n", 
                   apic->lapic_id.val, core->cpu_id, length);
-       goto apic_read_out_bad;
+       return -1;
     }
 
     PrintDebug("apic %u: core %u: Read finished (val=%x)\n", 
               apic->lapic_id.val, core->cpu_id, *(uint32_t *)dst);
 
-
-    // apic_read_out_good:
-    v3_unlock(apic->lock);
     return length;
-
- apic_read_out_bad:
-    v3_unlock(apic->lock);
-    return -1;
 }
 
 
@@ -1292,9 +1184,6 @@ static int apic_write(struct guest_info * core, addr_t guest_addr, void * src, u
     struct apic_msr * msr = (struct apic_msr *)&(apic->base_addr_msr.value);
     uint32_t op_val = *(uint32_t *)src;
 
-
-    v3_lock(apic->lock);
-
     PrintDebug("apic %u: core %u: at %p and priv_data is at %p\n",
               apic->lapic_id.val, core->cpu_id, apic, priv_data);
 
@@ -1304,14 +1193,14 @@ static int apic_write(struct guest_info * core, addr_t guest_addr, void * src, u
     if (msr->apic_enable == 0) {
        PrintError("apic %u: core %u: Write to APIC address space with disabled APIC, apic msr=0x%llx\n",
                   apic->lapic_id.val, core->cpu_id, apic->base_addr_msr.value);
-       goto apic_write_out_bad;
+       return -1;
     }
 
 
     if (length != 4) {
        PrintError("apic %u: core %u: Invalid apic write length (%d)\n", 
                   apic->lapic_id.val, length, core->cpu_id);
-       goto apic_write_out_bad;
+       return -1;
     }
 
     switch (reg_addr) {
@@ -1347,7 +1236,6 @@ static int apic_write(struct guest_info * core, addr_t guest_addr, void * src, u
 
            PrintError("apic %u: core %u: Attempting to write to read only register %p (error)\n", 
                       apic->lapic_id.val, core->cpu_id, (void *)reg_addr);
-           //  goto apic_write_out_bad;
 
            break;
 
@@ -1447,51 +1335,35 @@ static int apic_write(struct guest_info * core, addr_t guest_addr, void * src, u
 
            // Action Registers
        case EOI_OFFSET:
-           // do eoi (we already have the lock)
+           // do eoi 
            apic_do_eoi(apic);
            break;
 
        case INT_CMD_LO_OFFSET: {
-           // execute command (we already have the lock)
+           // execute command 
 
            struct int_cmd_reg tmp_icr;
 
            apic->int_cmd.lo = op_val;
 
-           tmp_icr=apic->int_cmd;
+           tmp_icr = apic->int_cmd;
 
            //      V3_Print("apic %u: core %u: sending cmd 0x%llx to apic %u\n", 
            //       apic->lapic_id.val, core->cpu_id,
            //       apic->int_cmd.val, apic->int_cmd.dst);
 
-           apic->in_icr=0;
-
-           v3_unlock(apic->lock);
-
-           // route_ipi is responsible for locking apics, so we go in unlocked)
            if (route_ipi(apic_dev, apic, &tmp_icr) == -1) { 
                PrintError("IPI Routing failure\n");
-               goto apic_write_out_bad;
+               return -1;
            }
-
-           //      v3_lock(apic->lock);  // expected for leaving this function
-
-       }
            break;
-
+       }
        case INT_CMD_HI_OFFSET: {
-           // already have the lock
-           if (apic->in_icr) { 
-               PrintError("apic %u: core %u: writing command high=0x%x while in_icr=1\n", apic->lapic_id.val, core->cpu_id,apic->int_cmd.hi);
-           }
-
            apic->int_cmd.hi = op_val;
-           //V3_Print("apic %u: core %u: writing command high=0x%x\n", apic->lapic_id.val, core->cpu_id,apic->int_cmd.hi);
-           apic->in_icr=1;
-       }
-           break;
-
+           V3_Print("apic %u: core %u: writing command high=0x%x\n", apic->lapic_id.val, core->cpu_id,apic->int_cmd.hi);
 
+           break;
+       }
        // Unhandled Registers
        case EXT_APIC_CMD_OFFSET:
        case SEOI_OFFSET:
@@ -1499,26 +1371,21 @@ static int apic_write(struct guest_info * core, addr_t guest_addr, void * src, u
            PrintError("apic %u: core %u: Write to Unhandled APIC Register: %x (ignored)\n", 
                       apic->lapic_id.val, core->cpu_id, (uint32_t)reg_addr);
 
-           goto apic_write_out_bad;
+           return -1;
     }
 
     PrintDebug("apic %u: core %u: Write finished\n", apic->lapic_id.val, core->cpu_id);
 
-    // apic_write_out_good:
-    v3_unlock(apic->lock);
     return length;
 
- apic_write_out_bad:
-    v3_unlock(apic->lock);
-    return -1;
 }
 
 
 
 /* Interrupt Controller Functions */
 
-// internally used, expects caller to lock
-static int apic_intr_pending_nolock(struct guest_info * core, void * private_data) {
+
+static int apic_intr_pending(struct guest_info * core, void * private_data) {
     struct apic_dev_state * apic_dev = (struct apic_dev_state *)(private_data);
     struct apic_state * apic = &(apic_dev->apics[core->cpu_id]); 
     int req_irq = get_highest_irr(apic);
@@ -1534,23 +1401,9 @@ static int apic_intr_pending_nolock(struct guest_info * core, void * private_dat
     return 0;
 }
 
-// externally visible, so must lock itself
-static int apic_intr_pending(struct guest_info * core, void * private_data) {
-    struct apic_dev_state * apic_dev = (struct apic_dev_state *)(private_data);
-    struct apic_state * apic = &(apic_dev->apics[core->cpu_id]); 
-    int rc;
 
-    v3_lock(apic->lock);
-    
-    rc=apic_intr_pending_nolock(core,private_data);
-    
-    v3_unlock(apic->lock);
-
-    return rc;
-}
 
-// Internal - no lock
-static int apic_get_intr_number_nolock(struct guest_info * core, void * private_data) {
+static int apic_get_intr_number(struct guest_info * core, void * private_data) {
     struct apic_dev_state * apic_dev = (struct apic_dev_state *)(private_data);
     struct apic_state * apic = &(apic_dev->apics[core->cpu_id]); 
     int req_irq = get_highest_irr(apic);
@@ -1566,25 +1419,7 @@ static int apic_get_intr_number_nolock(struct guest_info * core, void * private_
 }
 
 
-// Externally visible, so must lock itself
-static int apic_get_intr_number(struct guest_info * core, void * private_data) {
-    struct apic_dev_state * apic_dev = (struct apic_dev_state *)(private_data);
-    struct apic_state * apic = &(apic_dev->apics[core->cpu_id]); 
-    int rc;
-
-    v3_lock(apic->lock);
-    
-    rc=apic_get_intr_number_nolock(core,private_data);
-
-    v3_unlock(apic->lock);
-
-    return rc;
-}
-
 
-//
-// Here there is no source APIC, so there is no need to lock it
-// Furthermore, the expectation is that route_ipi will lock the destiation apic
 int v3_apic_send_ipi(struct v3_vm_info * vm, struct v3_gen_ipi * ipi, void * dev_data) {
     struct apic_dev_state * apic_dev = (struct apic_dev_state *)
        (((struct vm_device *)dev_data)->private_data);
@@ -1600,7 +1435,7 @@ int v3_apic_send_ipi(struct v3_vm_info * vm, struct v3_gen_ipi * ipi, void * dev
     tmp_icr.dst_shorthand = ipi->dst_shorthand;
     tmp_icr.dst = ipi->dst;
 
-    // route_ipi is responsible for locking the destination apic
+
     return route_ipi(apic_dev, NULL, &tmp_icr);
 }
 
@@ -1613,17 +1448,14 @@ int v3_apic_raise_intr(struct v3_vm_info * vm, uint32_t irq, uint32_t dst, void
 
     PrintDebug("apic %u core ?: raising interrupt IRQ %u (dst = %u).\n", apic->lapic_id.val, irq, dst); 
 
-    v3_lock(apic->lock);
-
-    do_xcall=activate_apic_irq_nolock(apic, irq);
+    do_xcall = activate_apic_irq(apic, irq);
 
-    if (do_xcall<0) { 
+    if (do_xcall < 0) { 
        PrintError("Failed to activate apic irq\n");
-       v3_unlock(apic->lock);
        return -1;
     }
     
-    if (do_xcall>0 && (V3_Get_CPU() != dst)) {
+    if (do_xcall > 0 && (V3_Get_CPU() != dst)) {
 #ifdef CONFIG_MULTITHREAD_OS
        v3_interrupt_cpu(vm, dst, 0);
 #else
@@ -1631,13 +1463,13 @@ int v3_apic_raise_intr(struct v3_vm_info * vm, uint32_t irq, uint32_t dst, void
 #endif
 
     }
-    v3_unlock(apic->lock);
+
     return 0;
 }
 
 
-// internal - caller must lock
-static int apic_begin_irq_nolock(struct guest_info * core, void * private_data, int irq) {
+
+static int apic_begin_irq(struct guest_info * core, void * private_data, int irq) {
     struct apic_dev_state * apic_dev = (struct apic_dev_state *)(private_data);
     struct apic_state * apic = &(apic_dev->apics[core->cpu_id]); 
     int major_offset = (irq & ~0x00000007) >> 3;
@@ -1660,26 +1492,13 @@ static int apic_begin_irq_nolock(struct guest_info * core, void * private_data,
     return 0;
 }
 
-// Since this is called, externally, it should lock the apic
-static int apic_begin_irq(struct guest_info * core, void * private_data, int irq) {
-    struct apic_dev_state * apic_dev = (struct apic_dev_state *)(private_data);
-    struct apic_state * apic = &(apic_dev->apics[core->cpu_id]); 
-    int rc;
 
-    v3_lock(apic->lock);
-
-    rc=apic_begin_irq_nolock(core,private_data,irq);
-
-    v3_unlock(apic->lock);
-
-    return rc;
-}
 
 
 
 /* Timer Functions */
-// Caller will lock the apic
-static void apic_update_time_nolock(struct guest_info * core, 
+
+static void apic_update_time(struct guest_info * core, 
                             uint64_t cpu_cycles, uint64_t cpu_freq, 
                             void * priv_data) {
     struct apic_dev_state * apic_dev = (struct apic_dev_state *)(priv_data);
@@ -1752,13 +1571,13 @@ static void apic_update_time_nolock(struct guest_info * core,
                   apic->lapic_id.val, core->cpu_id,
                   apic->tmr_vec_tbl.tmr_mode, apic->tmr_init_cnt, shift_num);
 
-       if (apic_intr_pending_nolock(core, priv_data)) {
+       if (apic_intr_pending(core, priv_data)) {
            PrintDebug("apic %u: core %u: Overriding pending IRQ %d\n", 
                       apic->lapic_id.val, core->cpu_id, 
                       apic_get_intr_number(core, priv_data));
        }
 
-       if (activate_internal_irq_nolock(apic, APIC_TMR_INT) == -1) {
+       if (activate_internal_irq(apic, APIC_TMR_INT) == -1) {
            PrintError("apic %u: core %u: Could not raise Timer interrupt\n",
                       apic->lapic_id.val, core->cpu_id);
        }
@@ -1773,21 +1592,6 @@ static void apic_update_time_nolock(struct guest_info * core,
 }
 
 
-static void apic_update_time(struct guest_info * core, 
-                            uint64_t cpu_cycles, uint64_t cpu_freq, 
-                            void * priv_data) {
-    struct apic_dev_state * apic_dev = (struct apic_dev_state *)(priv_data);
-    struct apic_state * apic = &(apic_dev->apics[core->cpu_id]); 
-
-    v3_lock(apic->lock);
-
-    apic_update_time_nolock(core,cpu_cycles,cpu_freq,priv_data);
-
-    v3_unlock(apic->lock);
-    
-    return;
-}
-
 static struct intr_ctrl_ops intr_ops = {
     .intr_pending = apic_intr_pending,
     .get_intr_number = apic_get_intr_number,
@@ -1847,8 +1651,6 @@ static int apic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
 
     apic_dev->num_apics = vm->num_cores;
 
-    //v3_lock_init(&(apic_dev->ipi_lock));
-
     struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, apic_dev);
 
     if (dev == NULL) {
index f3b2c0c..8e44ae5 100644 (file)
@@ -35,6 +35,9 @@ obj-y := \
        vmm_muxer.o \
        vmm_mem_hook.o \
        vmm_mptable.o \
+       vmm_extensions.o \
+       vmm_mtrr.o \
+
 
 obj-$(CONFIG_SVM) +=    svm.o \
                        svm_io.o \
index 72a1b58..bb65a6f 100644 (file)
@@ -459,12 +459,12 @@ int v3_svm_enter(struct guest_info * info) {
     // Perform any additional yielding needed for time adjustment
     v3_adjust_time(info);
 
-    // Update timer devices prior to entering VM.
-    v3_update_timers(info);
-
     // disable global interrupts for vm state transition
     v3_clgi();
 
+    // Update timer devices prior to entering VM.
+    v3_update_timers(info);
+
     // Synchronize the guest state to the VMCB
     guest_state->cr0 = info->ctrl_regs.cr0;
     guest_state->cr2 = info->ctrl_regs.cr2;
@@ -514,7 +514,7 @@ int v3_svm_enter(struct guest_info * info) {
 
     //V3_Print("Calling v3_svm_launch\n");
 
-    v3_svm_launch((vmcb_t *)V3_PAddr(info->vmm_data), &(info->vm_regs), (vmcb_t *)host_vmcbs[info->host_cpu_id]);
+    v3_svm_launch((vmcb_t *)V3_PAddr(info->vmm_data), &(info->vm_regs), (vmcb_t *)host_vmcbs[V3_Get_CPU()]);
 
     //V3_Print("SVM Returned: Exit Code: %x, guest_rip=%lx\n", (uint32_t)(guest_ctrl->exit_code), (unsigned long)guest_state->rip);
 
index 9acfbd0..c890fda 100644 (file)
@@ -24,6 +24,7 @@
 #include <palacios/vmm_ctrl_regs.h>
 #include <palacios/vmm_lowlevel.h>
 #include <palacios/vmm_sprintf.h>
+#include <palacios/vmm_extensions.h>
 
 #ifdef CONFIG_SVM
 #include <palacios/svm.h>
@@ -39,7 +40,6 @@
 
 v3_cpu_arch_t v3_cpu_types[CONFIG_MAX_CPUS];
 struct v3_os_hooks * os_hooks = NULL;
-
 int v3_dbg_enable = 0;
 
 
@@ -113,6 +113,9 @@ void Init_V3(struct v3_os_hooks * hooks, int num_cpus) {
     // Register all shadow paging handlers
     V3_init_shdw_paging();
 
+    // Register all extensions
+    V3_init_extensions();
+
 
 #ifdef CONFIG_SYMMOD
     V3_init_symmod();
@@ -146,6 +149,8 @@ void Shutdown_V3() {
     V3_deinit_devices();
     V3_deinit_shdw_paging();
 
+    V3_deinit_extensions();
+
 #ifdef CONFIG_SYMMOD
     V3_deinit_symmod();
 #endif
@@ -204,12 +209,10 @@ static int start_core(void * p)
     struct guest_info * core = (struct guest_info *)p;
 
 
-    PrintDebug("virtual core %u/physical core %u: in start_core (RIP=%p)\n", 
-              core->cpu_id, core->host_cpu_id, (void *)(addr_t)core->rip);
-
+    PrintDebug("virtual core %u: in start_core (RIP=%p)\n", 
+              core->cpu_id, (void *)(addr_t)core->rip);
 
-    // JRL: Whoa WTF? cpu_types are tied to the vcoreID????
-    switch (v3_cpu_types[core->host_cpu_id]) {
+    switch (v3_cpu_types[0]) {
 #ifdef CONFIG_SVM
        case V3_SVM_CPU:
        case V3_SVM_REV3_CPU:
@@ -243,52 +246,67 @@ int v3_start_vm(struct v3_vm_info * vm, unsigned int cpu_mask) {
     uint32_t i;
     uint8_t * core_mask = (uint8_t *)&cpu_mask; // This is to make future expansion easier
     uint32_t avail_cores = 0;
+    int vcore_id = 0;
 
     /// CHECK IF WE ARE MULTICORE ENABLED....
 
     V3_Print("V3 --  Starting VM (%u cores)\n", vm->num_cores);
     V3_Print("CORE 0 RIP=%p\n", (void *)(addr_t)(vm->cores[0].rip));
 
-    if (vm->num_cores > MAX_CORES ) {
-       PrintError("Attempted to start a VM with too many cores (vm->num_cores = %d, avail_cores = %d, MAX=%d)\n", vm->num_cores, avail_cores, MAX_CORES);
-       return -1;
+
+    // Check that enough cores are present in the mask to handle vcores
+    for (i = 0; i < MAX_CORES; i++) {
+       int major = i / 8;
+       int minor = i % 8;
+       
+       if (core_mask[major] & (0x1 << minor)) {
+           avail_cores++;
+       }
     }
 
-    if (vm->cores[0].host_cpu_id != 0) {
-       PrintError("First virtual core must run on host core 0.\n");
+
+    if (vm->num_cores > avail_cores) {
+       PrintError("Attempted to start a VM with too many cores (vm->num_cores = %d, avail_cores = %d, MAX=%d)\n", vm->num_cores, avail_cores, MAX_CORES);
        return -1;
     }
 
 #ifdef CONFIG_MULTITHREAD_OS
     // spawn off new threads, for other cores
-    for (i = 1; i < vm->num_cores; i++) {
-       struct guest_info *core = &(vm->cores[i]);
-       int major = core->host_cpu_id / 8;
-       int minor = core->host_cpu_id % 8;
+    for (i = 0, vcore_id = 1; (i < MAX_CORES) && (vcore_id < vm->num_cores); i++) {
+       int major = i / 8;
+       int minor = i % 8;
        void * core_thread = NULL;
+       struct guest_info * core = &(vm->cores[vcore_id]);
+
+       /* This assumes that the core 0 thread has been mapped to physical core 0 */
+       if (i == V3_Get_CPU()) {
+           // We skip the local CPU because it is reserved for vcore 0
+           continue;
+       }
 
        if ((core_mask[major] & (0x1 << minor)) == 0) {
-           PrintError("Host CPU %d not available for virtual core %d; not started\n",
-                      core->host_cpu_id, i);
+           PrintError("Logical CPU %d not available for virtual core %d; not started\n",
+                      i, vcore_id);
            continue;
        } 
 
        PrintDebug("Starting virtual core %u on logical core %u\n", 
-                  i, core->host_cpu_id);
+                  vcore_id, i);
        
-       sprintf(core->exec_name, "%s-%u", vm->name, i);
+       sprintf(core->exec_name, "%s-%u", vm->name, vcore_id);
 
        PrintDebug("run: core=%u, func=0x%p, arg=0x%p, name=%s\n",
-                  core->host_cpu_id, start_core, core, core->exec_name);
+                  i, start_core, core, core->exec_name);
 
        // TODO: actually manage these threads instead of just launching them
-       core_thread = V3_CREATE_THREAD_ON_CPU(core->host_cpu_id, start_core,
-                                             core, core->exec_name);
+       core_thread = V3_CREATE_THREAD_ON_CPU(i, start_core, core, core->exec_name);
 
        if (core_thread == NULL) {
            PrintError("Thread launch failed\n");
            return -1;
        }
+
+       vcore_id++;
     }
 #endif
 
@@ -460,7 +478,7 @@ void v3_interrupt_cpu(struct v3_vm_info * vm, int logical_cpu, int vector) {
 
 
 int v3_vm_enter(struct guest_info * info) {
-    switch (v3_cpu_types[info->host_cpu_id]) {
+    switch (v3_cpu_types[0]) {
 #ifdef CONFIG_SVM
        case V3_SVM_CPU:
        case V3_SVM_REV3_CPU:
index 8844dee..d97beac 100644 (file)
@@ -292,7 +292,8 @@ static int determine_paging_mode(struct guest_info * info, v3_cfg_tree_t * core_
 
     if (pg_mode) {
        if ((strcasecmp(pg_mode, "nested") == 0)) {
-           if (v3_cpu_types[info->host_cpu_id] == V3_SVM_REV3_CPU) {
+           // we assume symmetric cores, so if core 0 has nested paging they all do
+           if (v3_cpu_types[0] == V3_SVM_REV3_CPU) {
                info->shdw_pg_mode = NESTED_PAGING;
            } else {
                PrintError("Nested paging not supported on this hardware. Defaulting to shadow paging\n");
@@ -338,21 +339,9 @@ static int determine_paging_mode(struct guest_info * info, v3_cfg_tree_t * core_
 }
 
 static int pre_config_core(struct guest_info * info, v3_cfg_tree_t * core_cfg) {
-    char *hcpu;
-    if (determine_paging_mode(info, core_cfg))
+    if (determine_paging_mode(info, core_cfg) != 0) {
        return -1;
-
-    hcpu = v3_cfg_val(core_cfg, "hostcpu");
-    if (hcpu) {
-       int req_id = atoi(hcpu);
-       if (req_id < 0) {
-           PrintError("Invalid host core %d requested by"
-                      " virtual cpu %d - ignored.\n", req_id, info->cpu_id);
-       } else {
-               PrintDebug("Assigned host core %d to virtual core %d.\n", info->cpu_id, req_id);
-           info->host_cpu_id = req_id;
-       }
-    } 
+    }
 
     v3_init_core(info);
 
@@ -505,7 +494,6 @@ struct v3_vm_info * v3_config_guest(void * cfg_blob, void * priv_data) {
        info->cpu_id = i;
        info->vm_info = vm;
        info->core_cfg_data = per_core_cfg;
-       info->host_cpu_id = i; // may be overriden by core config
 
        if (pre_config_core(info, per_core_cfg) == -1) {
            PrintError("Error in core %d preconfiguration\n", i);
diff --git a/palacios/src/palacios/vmm_extensions.c b/palacios/src/palacios/vmm_extensions.c
new file mode 100644 (file)
index 0000000..40a0dd0
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National 
+ * Science Foundation and the Department of Energy.  
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico.  You can find out more at 
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
+ * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
+ * All rights reserved.
+ *
+ * Author: Jack Lange <jarusl@cs.northwestern.edu>
+ *
+ * This is free software.  You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#include <palacios/vmm.h>
+
+#include <palacios/vmm_extensions.h>
+
+#include <palacios/vmm_hashtable.h>
+
+
+static struct hashtable * ext_table = NULL;
+
+
+static uint_t ext_hash_fn(addr_t key) {
+    char * name = (char *)key;
+    return v3_hash_buffer((uint8_t *)name, strlen(name));
+}
+
+static int ext_eq_fn(addr_t key1, addr_t key2) {
+    char * name1 = (char *)key1;
+    char * name2 = (char *)key2;
+
+    return (strcmp(name1, name2) == 0);
+}
+
+
+
+int V3_init_extensions() {
+    extern struct v3_extension_impl * __start__v3_extensions[];
+    extern struct v3_extension_impl * __stop__v3_extensions[];
+    struct v3_extension_impl ** tmp_ext = __start__v3_extensions;
+    int i = 0;
+
+    ext_table = v3_create_htable(0, ext_hash_fn, ext_eq_fn);
+
+    while (tmp_ext != __stop__v3_extensions) {
+       V3_Print("Registering Extension (%s)\n", (*tmp_ext)->name);
+
+       if (v3_htable_search(ext_table, (addr_t)((*tmp_ext)->name))) {
+           PrintError("Multiple instances of Extension (%s)\n", (*tmp_ext)->name);
+           return -1;
+       }
+
+       if (v3_htable_insert(ext_table, (addr_t)((*tmp_ext)->name), (addr_t)(*tmp_ext)) == 0) {
+           PrintError("Could not register Extension (%s)\n", (*tmp_ext)->name);
+           return -1;
+       }
+
+       tmp_ext = &(__start__v3_extensions[++i]);
+    }
+
+    return 0;
+}
+
+
+int V3_deinit_extensions() {
+    v3_free_htable(ext_table, 0, 0);
+    return 0;
+}
+
+
diff --git a/palacios/src/palacios/vmm_mtrr.c b/palacios/src/palacios/vmm_mtrr.c
new file mode 100644 (file)
index 0000000..4c563ce
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National 
+ * Science Foundation and the Department of Energy.  
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico.  You can find out more at 
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2011, Jack Lange <jarusl@cs.northwestern.edu> 
+ * Copyright (c) 2011, The V3VEE Project <http://www.v3vee.org> 
+ * All rights reserved.
+ *
+ * Author: Jack Lange <jarusl@cs.northwestern.edu>
+ *
+ * This is free software.  You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#include <palacios/vmm_mtrr.h>
+#include <palacios/vmm_extensions.h>
+#include <palacios/vmm.h>
+#include <palacios/vm_guest.h>
+#include <palacios/vmm_msr.h>
+
+
+#define MTRR_CAP_MSR       0x00fe
+#define MTRR_PHYS_BASE_0   0x0200
+#define MTRR_PHYS_BASE_1   0x0202
+#define MTRR_PHYS_BASE_2   0x0204
+#define MTRR_PHYS_BASE_3   0x0206
+#define MTRR_PHYS_BASE_4   0x0208
+#define MTRR_PHYS_BASE_5   0x020a
+#define MTRR_PHYS_BASE_6   0x020c
+#define MTRR_PHYS_BASE_7   0x020e
+#define MTRR_PHYS_MASK_0   0x0201
+#define MTRR_PHYS_MASK_1   0x0203
+#define MTRR_PHYS_MASK_2   0x0205
+#define MTRR_PHYS_MASK_3   0x0207
+#define MTRR_PHYS_MASK_4   0x0209
+#define MTRR_PHYS_MASK_5   0x020b
+#define MTRR_PHYS_MASK_6   0x020d
+#define MTRR_PHYS_MASK_7   0x020f
+#define MTRR_FIX_64K_00000 0x0250
+#define MTRR_FIX_16K_80000 0x0258
+#define MTRR_FIX_16K_A0000 0x0259
+#define MTRR_FIX_4K_C0000  0x0268
+#define MTRR_FIX_4K_C8000  0x0269
+#define MTRR_FIX_4K_D0000  0x026a
+#define MTRR_FIX_4K_D8000  0x026b
+#define MTRR_FIX_4K_E0000  0x026c
+#define MTRR_FIX_4K_E8000  0x026d
+#define MTRR_FIX_4K_F0000  0x026e
+#define MTRR_FIX_4K_F8000  0x026f
+
+
+struct mtrr_cap {
+
+
+};
+
+
+struct mtrr_state {
+    struct mtrr_cap cap;
+    
+};
+
+
+static int mtrr_cap_read(struct guest_info * core, uint32_t msr, struct v3_msr * dst, void * priv_data) {
+    return 0;
+}
+
+static int mtrr_cap_write(struct guest_info * core, uint32_t msr, struct v3_msr src, void * priv_data) {
+
+    return 0;
+}
+
+
+
+static int init_mtrrs(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
+
+
+
+    v3_hook_msr(vm, MTRR_CAP_MSR, mtrr_cap_read, mtrr_cap_write, NULL);
+        
+
+    return 0;
+}
+
+
+struct v3_extension_impl mtrr_ext = {
+    .name = "MTRRS",
+    .init = init_mtrrs,
+    .deinit = NULL,
+    .core_init = NULL,
+    .core_deinit = NULL
+};
+
+
+
+register_extension(&mtrr_ext);
index 3b41305..32ef348 100644 (file)
@@ -32,11 +32,11 @@ static int cpuid_fn(struct guest_info * core, uint32_t cpuid,
 
     *eax = *(uint32_t *)"V3V";
 
-    if ((v3_cpu_types[core->host_cpu_id] == V3_SVM_CPU) || 
-       (v3_cpu_types[core->host_cpu_id] == V3_SVM_REV3_CPU)) {
+    if ((v3_cpu_types[0] == V3_SVM_CPU) || 
+       (v3_cpu_types[0] == V3_SVM_REV3_CPU)) {
        *ebx = *(uint32_t *)"SVM";
-    } else if ((v3_cpu_types[core->host_cpu_id] == V3_VMX_CPU) || 
-              (v3_cpu_types[core->host_cpu_id] == V3_VMX_EPT_CPU)) {
+    } else if ((v3_cpu_types[0] == V3_VMX_CPU) || 
+              (v3_cpu_types[0] == V3_VMX_EPT_CPU)) {
        *ebx = *(uint32_t *)"VMX";
     }
 
index dea7cdb..2880f5d 100644 (file)
@@ -86,11 +86,13 @@ int v3_start_time(struct guest_info * info) {
     uint64_t t = v3_get_host_time(&info->time_state); 
 
     PrintDebug("Starting initial guest time as %llu\n", t);
+
     info->time_state.enter_time = 0;
     info->time_state.exit_time = t; 
     info->time_state.last_update = t;
     info->time_state.initial_time = t;
     info->yield_start_cycle = t;
+
     return 0;
 }
 
@@ -113,11 +115,14 @@ int v3_adjust_time(struct guest_info * info) {
      * sync up. */
     host_time = v3_get_host_time(time_state);
     old_guest_time = v3_get_guest_time(time_state);
+
     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);
+
     // 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);
@@ -136,10 +141,11 @@ int v3_adjust_time(struct guest_info * info) {
        uint64_t max_skew, desired_skew, skew;
 
        if (time_state->enter_time) {
-           max_skew = (time_state->exit_time - time_state->enter_time)/10;
+           max_skew = (time_state->exit_time - time_state->enter_time) / 10;
        } else {
            max_skew = 0;
        }
+
        desired_skew = target_guest_time - guest_time;
        skew = desired_skew > max_skew ? max_skew : desired_skew;
 /*     PrintDebug("Guest %llu cycles behind where it should be.\n",
@@ -241,8 +247,10 @@ void v3_update_timers(struct guest_info * info) {
 
 int v3_rdtsc(struct guest_info * info) {
     uint64_t tscval = v3_get_guest_tsc(&info->time_state);
+
     info->vm_regs.rdx = tscval >> 32;
     info->vm_regs.rax = tscval & 0xffffffffLL;
+
     return 0;
 }
 
@@ -393,8 +401,10 @@ void v3_init_time_core(struct guest_info * info) {
                   info->cpu_id, time_state->guest_cpu_freq);
     } 
     
-    if ((khz == NULL) || (time_state->guest_cpu_freq <= 0) 
-       || (time_state->guest_cpu_freq > time_state->host_cpu_freq)) {
+    if ( (khz == NULL) || 
+        (time_state->guest_cpu_freq <= 0)  || 
+        (time_state->guest_cpu_freq > time_state->host_cpu_freq) ) {
+
        time_state->guest_cpu_freq = time_state->host_cpu_freq;
     }
 
@@ -413,8 +423,6 @@ void v3_init_time_core(struct guest_info * info) {
     
     time_state->tsc_aux.lo = 0;
     time_state->tsc_aux.hi = 0;
-
-
 }
 
 
@@ -428,9 +436,3 @@ void v3_deinit_time_core(struct guest_info * core) {
     }
 
 }
-
-
-
-
-
-