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.


Jack's changes to split up stucts for multi-core.
Kevin Pedretti [Fri, 15 Jan 2010 00:27:40 +0000 (17:27 -0700)]
Merge branch 'devel' of ssh://ktpedre@newskysaw.cs.northwestern.edu/home/palacios/palacios into devel

Conflicts:
palacios/src/devices/keyboard.c

1  2 
palacios/include/palacios/vmm.h
palacios/src/devices/apic.c
palacios/src/palacios/svm.c

@@@ -148,34 -148,16 +148,34 @@@ struct guest_info
      } while (0)
  
  
- #define V3_Hook_Interrupt(irq, opaque) ({                             \
+ #define V3_Hook_Interrupt(vm, irq) ({                                 \
            int ret = 0;                                                \
            extern struct v3_os_hooks * os_hooks;                       \
            if ((os_hooks) && (os_hooks)->hook_interrupt) {             \
-               ret = (os_hooks)->hook_interrupt(irq, opaque);          \
+               ret = (os_hooks)->hook_interrupt(vm, irq);              \
            }                                                           \
            ret;                                                        \
        })                                                              \
        
  
 +#define V3_Get_CPU() ({                                               \
 +            int ret = 0;                                                \
 +            extern struct v3_os_hooks * os_hooks;                       \
 +            if ((os_hooks) && (os_hooks)->get_cpu) {                    \
 +                ret = (os_hooks)->get_cpu();                            \
 +            }                                                           \
 +            ret;                                                        \
 +        })
 +
 +#define V3_Call_On_CPU(cpu, fn, arg)                  \
 +    do {                                              \
 +        extern struct v3_os_hooks * os_hooks;           \
 +        if ((os_hooks) && (os_hooks)->call_on_cpu) {    \
 +            (os_hooks)->call_on_cpu(cpu, fn, arg);      \
 +        }                                               \
 +    } while (0)
 +
 +
  #define V3_ACK_IRQ(irq)                                               \
      do {                                                      \
        extern struct v3_os_hooks * os_hooks;                   \
@@@ -218,7 -200,7 +218,7 @@@ void v3_yield_cond(struct guest_info * 
  void v3_print_cond(const char * fmt, ...);
  
  
- void v3_interrupt_cpu(struct guest_info * vm, int logical_cpu);
+ void v3_interrupt_cpu(struct v3_vm_info * vm, int logical_cpu);
  
  unsigned int v3_get_cpu_id();
  
@@@ -232,7 -214,7 +232,7 @@@ int v3_vm_enter(struct guest_info * inf
  
  
  
- struct guest_info;
+ struct v3_vm_info;
  
  /* This will contain function pointers that provide OS services */
  struct v3_os_hooks {
      void *(*paddr_to_vaddr)(void *addr);
      void *(*vaddr_to_paddr)(void *addr);
  
-     int (*hook_interrupt)(struct guest_info * vm, unsigned int irq);
+     int (*hook_interrupt)(struct v3_vm_info * vm, unsigned int irq);
  
      int (*ack_irq)(int irq);
  
      void (*mutex_unlock)(void * mutex);
  
      unsigned int (*get_cpu)(void);
-     void (*interrupt_cpu)(struct guest_info * vm, int logical_cpu);
+     void (*interrupt_cpu)(struct v3_vm_info * vm, int logical_cpu);
      void (*call_on_cpu)(int logical_cpu, void (*fn)(void * arg), void * arg);
      void (*start_thread_on_cpu)(int logical_cpu, int (*fn)(void * arg), void * arg, char * thread_name);
  };
@@@ -293,10 -275,10 +293,10 @@@ struct v3_interrupt 
  void Init_V3(struct v3_os_hooks * hooks,  int num_cpus);
  
  
- int v3_start_vm(struct guest_info * info, unsigned int cpu_mask);
- struct guest_info * v3_create_vm(void * cfg);
+ int v3_start_vm(struct v3_vm_info * vm, unsigned int cpu_mask);
+ struct v3_vm_info * v3_create_vm(void * cfg);
  
- int v3_deliver_irq(struct guest_info * vm, struct v3_interrupt * intr);
+ int v3_deliver_irq(struct v3_vm_info * vm, struct v3_interrupt * intr);
  
  
  
@@@ -22,7 -22,6 +22,7 @@@
  #include <devices/apic_regs.h>
  #include <palacios/vmm.h>
  #include <palacios/vmm_msr.h>
 +#include <palacios/vmm_sprintf.h>
  #include <palacios/vm_guest.h>
  
  #ifndef CONFIG_DEBUG_APIC
@@@ -182,9 -181,9 +182,10 @@@ struct apic_state 
      uint32_t eoi;
  
  
+     struct guest_info * core;
  };
  
 +static void apic_incoming_ipi(void *val);
  static int apic_read(addr_t guest_addr, void * dst, uint_t length, void * priv_data);
  static int apic_write(addr_t guest_addr, void * src, uint_t length, void * priv_data);
  
@@@ -285,7 -284,7 +286,7 @@@ static int activate_apic_irq(struct api
      PrintDebug("Raising APIC IRQ %d\n", irq_num);
  
      if (*req_location & flag) {
 -      V3_Print("Interrupts coallescing\n");
 +      //V3_Print("Interrupts coallescing\n");
      }
  
      if (*en_location & flag) {
@@@ -370,7 -369,7 +371,7 @@@ static int apic_do_eoi(struct apic_stat
        }
  #endif
      } else {
 -      PrintError("Spurious EOI...\n");
 +      //PrintError("Spurious EOI...\n");
      }
        
      return 0;
@@@ -846,13 -845,7 +847,13 @@@ static int apic_write(addr_t guest_addr
            break;
  
        case INT_CMD_LO_OFFSET:
 +          apic->int_cmd.lo = op_val;
 +          V3_Call_On_CPU(apic->int_cmd.dst, apic_incoming_ipi, (void *)apic->int_cmd.val);
 +    
 +          break;
        case INT_CMD_HI_OFFSET:
 +          apic->int_cmd.hi = op_val;
 +          break;
            // Unhandled Registers
  
        case EXT_APIC_CMD_OFFSET:
@@@ -959,7 -952,7 +960,7 @@@ int v3_apic_raise_intr(struct guest_inf
  
  
  /* Timer Functions */
- static void apic_update_time(ullong_t cpu_cycles, ullong_t cpu_freq, void * priv_data) {
+ static void apic_update_time(struct guest_info * info, ullong_t cpu_cycles, ullong_t cpu_freq, void * priv_data) {
      struct vm_device * dev = (struct vm_device *)priv_data;
      struct apic_state * apic = (struct apic_state *)dev->private_data;
      // The 32 bit GCC runtime is a pile of shit
        PrintDebug("Raising APIC Timer interrupt (periodic=%d) (icnt=%d) (div=%d)\n", 
                   apic->tmr_vec_tbl.tmr_mode, apic->tmr_init_cnt, shift_num);
  
-       if (apic_intr_pending(dev->vm, priv_data)) {
+       if (apic_intr_pending(info, priv_data)) {
            PrintDebug("Overriding pending IRQ %d\n", apic_get_intr_number(dev->vm, priv_data));
        }
  
  
  }
  
 +static void apic_incoming_ipi(void *val)
 +{
 +PrintError("In apic_incoming_ipi, val=%p\n", val);
 +      struct int_cmd_reg int_cmd;
 +      char *type = NULL, *dest;
 +      char foo[8];
 +      int_cmd.val = (uint64_t)val;
 +      switch (int_cmd.dst_shorthand)
 +      {
 +      case 0x0:
 +              sprintf(foo, "%d", int_cmd.dst);
 +              dest = foo;
 +              break;
 +      case 0x1:
 +              dest = "(self)";
 +              break;
 +      case 0x2:
 +              dest = "(broadcast inclusive)";
 +              break;
 +      case 0x3:
 +              dest = "(broadcast)";
 +              break;
 +      }
 +      switch (int_cmd.msg_type) 
 +      {
 +      case 0x0:
 +              type = "";
 +              break;
 +      case 0x4:
 +              type = "(NMI)";
 +              break;
 +      case 0x5:
 +              type = "(INIT)";
 +              break;
 +      case 0x6:
 +              type = "(Startup)";
 +              break;
 +      }
 +      PrintError("Receieved IPI on CPU %d type=%s dest=%s\n",
 +                      V3_Get_CPU(), type, dest);
 +//%p %s to CPU %d on CPU %d.\n", val, foo, type, dest, (int)V3_Get_CPU());
 +      return;
 +}
  
  
  static struct intr_ctrl_ops intr_ops = {
@@@ -1106,9 -1056,9 +1107,9 @@@ static struct vm_timer_ops timer_ops = 
  
  
  static int apic_free(struct vm_device * dev) {
-     struct guest_info * info = dev->vm;
+     //   struct apic_state * apic = (struct apic_state *)dev->private_data;
  
-     v3_unhook_msr(info, BASE_ADDR_MSR);
+     v3_unhook_msr(dev->vm, BASE_ADDR_MSR);
  
      return 0;
  }
@@@ -1123,7 -1073,7 +1124,7 @@@ static struct v3_device_ops dev_ops = 
  
  
  
- static int apic_init(struct guest_info * vm, v3_cfg_tree_t * cfg) {
+ static int apic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
      PrintDebug("Creating APIC\n");
      char * name = v3_cfg_val(cfg, "name");
  
@@@ -67,7 -67,7 +67,7 @@@ static vmcb_t * Allocate_VMCB() 
  
  
  
- static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info * vm_info) {
+ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info * core) {
      vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA(vmcb);
      vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA(vmcb);
      uint_t i;
  
      /* Setup Guest Machine state */
  
-     vm_info->vm_regs.rsp = 0x00;
-     vm_info->rip = 0xfff0;
+     core->vm_regs.rsp = 0x00;
+     core->rip = 0xfff0;
  
-     vm_info->vm_regs.rdx = 0x00000f00;
+     core->vm_regs.rdx = 0x00000f00;
  
  
-     vm_info->cpl = 0;
+     core->cpl = 0;
  
-     vm_info->ctrl_regs.rflags = 0x00000002; // The reserved bit is always 1
-     vm_info->ctrl_regs.cr0 = 0x60010010; // Set the WP flag so the memory hooks work in real-mode
-     vm_info->ctrl_regs.efer |= EFER_MSR_svm_enable;
+     core->ctrl_regs.rflags = 0x00000002; // The reserved bit is always 1
+     core->ctrl_regs.cr0 = 0x60010010; // Set the WP flag so the memory hooks work in real-mode
+     core->ctrl_regs.efer |= EFER_MSR_svm_enable;
  
  
  
  
  
-     vm_info->segments.cs.selector = 0xf000;
-     vm_info->segments.cs.limit = 0xffff;
-     vm_info->segments.cs.base = 0x0000000f0000LL;
+     core->segments.cs.selector = 0xf000;
+     core->segments.cs.limit = 0xffff;
+     core->segments.cs.base = 0x0000000f0000LL;
  
      // (raw attributes = 0xf3)
-     vm_info->segments.cs.type = 0x3;
-     vm_info->segments.cs.system = 0x1;
-     vm_info->segments.cs.dpl = 0x3;
-     vm_info->segments.cs.present = 1;
+     core->segments.cs.type = 0x3;
+     core->segments.cs.system = 0x1;
+     core->segments.cs.dpl = 0x3;
+     core->segments.cs.present = 1;
  
  
  
-     struct v3_segment * segregs [] = {&(vm_info->segments.ss), &(vm_info->segments.ds), 
-                                     &(vm_info->segments.es), &(vm_info->segments.fs), 
-                                     &(vm_info->segments.gs), NULL};
+     struct v3_segment * segregs [] = {&(core->segments.ss), &(core->segments.ds), 
+                                     &(core->segments.es), &(core->segments.fs), 
+                                     &(core->segments.gs), NULL};
  
      for ( i = 0; segregs[i] != NULL; i++) {
        struct v3_segment * seg = segregs[i];
        seg->present = 1;
      }
  
-     vm_info->segments.gdtr.limit = 0x0000ffff;
-     vm_info->segments.gdtr.base = 0x0000000000000000LL;
-     vm_info->segments.idtr.limit = 0x0000ffff;
-     vm_info->segments.idtr.base = 0x0000000000000000LL;
+     core->segments.gdtr.limit = 0x0000ffff;
+     core->segments.gdtr.base = 0x0000000000000000LL;
+     core->segments.idtr.limit = 0x0000ffff;
+     core->segments.idtr.base = 0x0000000000000000LL;
  
-     vm_info->segments.ldtr.selector = 0x0000;
-     vm_info->segments.ldtr.limit = 0x0000ffff;
-     vm_info->segments.ldtr.base = 0x0000000000000000LL;
-     vm_info->segments.tr.selector = 0x0000;
-     vm_info->segments.tr.limit = 0x0000ffff;
-     vm_info->segments.tr.base = 0x0000000000000000LL;
+     core->segments.ldtr.selector = 0x0000;
+     core->segments.ldtr.limit = 0x0000ffff;
+     core->segments.ldtr.base = 0x0000000000000000LL;
+     core->segments.tr.selector = 0x0000;
+     core->segments.tr.limit = 0x0000ffff;
+     core->segments.tr.base = 0x0000000000000000LL;
  
  
-     vm_info->dbg_regs.dr6 = 0x00000000ffff0ff0LL;
-     vm_info->dbg_regs.dr7 = 0x0000000000000400LL;
+     core->dbg_regs.dr6 = 0x00000000ffff0ff0LL;
+     core->dbg_regs.dr7 = 0x0000000000000400LL;
  
  
-     v3_init_svm_io_map(vm_info);
-     ctrl_area->IOPM_BASE_PA = (addr_t)V3_PAddr(vm_info->io_map.arch_data);
+     /** THESE NEED TO BE MOVED TO GLOBAL LOCATION **/
+     v3_init_svm_io_map(core->vm_info);
+     ctrl_area->IOPM_BASE_PA = (addr_t)V3_PAddr(core->vm_info->io_map.arch_data);
      ctrl_area->instrs.IOIO_PROT = 1;
  
-     v3_init_svm_msr_map(vm_info);
-     ctrl_area->MSRPM_BASE_PA = (addr_t)V3_PAddr(vm_info->msr_map.arch_data);
+     v3_init_svm_msr_map(core->vm_info);
+     ctrl_area->MSRPM_BASE_PA = (addr_t)V3_PAddr(core->vm_info->msr_map.arch_data);
      ctrl_area->instrs.MSR_PROT = 1;
+     /** *** **/
  
  
      PrintDebug("Exiting on interrupts\n");
      ctrl_area->instrs.INTR = 1;
  
  
-     if (vm_info->shdw_pg_mode == SHADOW_PAGING) {
+     if (core->shdw_pg_mode == SHADOW_PAGING) {
        PrintDebug("Creating initial shadow page table\n");
        
        /* JRL: This is a performance killer, and a simplistic solution */
        ctrl_area->guest_ASID = 1;
        
        
-       if (v3_init_passthrough_pts(vm_info) == -1) {
+       if (v3_init_passthrough_pts(core) == -1) {
            PrintError("Could not initialize passthrough page tables\n");
            return ;
        }
  
  
-       vm_info->shdw_pg_state.guest_cr0 = 0x0000000000000010LL;
+       core->shdw_pg_state.guest_cr0 = 0x0000000000000010LL;
        PrintDebug("Created\n");
        
-       vm_info->ctrl_regs.cr0 |= 0x80000000;
-       vm_info->ctrl_regs.cr3 = vm_info->direct_map_pt;
+       core->ctrl_regs.cr0 |= 0x80000000;
+       core->ctrl_regs.cr3 = core->direct_map_pt;
  
        ctrl_area->cr_reads.cr0 = 1;
        ctrl_area->cr_writes.cr0 = 1;
        ctrl_area->cr_reads.cr3 = 1;
        ctrl_area->cr_writes.cr3 = 1;
  
-       v3_hook_msr(vm_info, EFER_MSR, 
+       v3_hook_msr(core->vm_info, EFER_MSR, 
                    &v3_handle_efer_read,
                    &v3_handle_efer_write, 
-                   vm_info);
+                   core);
  
        ctrl_area->instrs.INVLPG = 1;
  
  
  
  
-     } else if (vm_info->shdw_pg_mode == NESTED_PAGING) {
+     } else if (core->shdw_pg_mode == NESTED_PAGING) {
        // Flush the TLB on entries/exits
        ctrl_area->TLB_CONTROL = 1;
        ctrl_area->guest_ASID = 1;
        PrintDebug("NP_Enable at 0x%p\n", (void *)&(ctrl_area->NP_ENABLE));
  
        // Set the Nested Page Table pointer
-       if (v3_init_passthrough_pts(vm_info) == -1) {
+       if (v3_init_passthrough_pts(core) == -1) {
            PrintError("Could not initialize Nested page tables\n");
            return ;
        }
  
-       ctrl_area->N_CR3 = vm_info->direct_map_pt;
+       ctrl_area->N_CR3 = core->direct_map_pt;
  
        guest_state->g_pat = 0x7040600070406ULL;
      }
@@@ -289,25 -290,25 +290,25 @@@ int v3_init_svm_vmcb(struct guest_info 
  static int update_irq_exit_state(struct guest_info * info) {
      vmcb_ctrl_t * guest_ctrl = GET_VMCB_CTRL_AREA((vmcb_t*)(info->vmm_data));
  
-     if ((info->intr_state.irq_pending == 1) && (guest_ctrl->guest_ctrl.V_IRQ == 0)) {
+     if ((info->intr_core_state.irq_pending == 1) && (guest_ctrl->guest_ctrl.V_IRQ == 0)) {
        
  #ifdef CONFIG_DEBUG_INTERRUPTS
-       PrintDebug("INTAK cycle completed for irq %d\n", info->intr_state.irq_vector);
+       PrintDebug("INTAK cycle completed for irq %d\n", info->intr_core_state.irq_vector);
  #endif
  
-       info->intr_state.irq_started = 1;
-       info->intr_state.irq_pending = 0;
+       info->intr_core_state.irq_started = 1;
+       info->intr_core_state.irq_pending = 0;
  
-       v3_injecting_intr(info, info->intr_state.irq_vector, V3_EXTERNAL_IRQ);
+       v3_injecting_intr(info, info->intr_core_state.irq_vector, V3_EXTERNAL_IRQ);
      }
  
-     if ((info->intr_state.irq_started == 1) && (guest_ctrl->exit_int_info.valid == 0)) {
+     if ((info->intr_core_state.irq_started == 1) && (guest_ctrl->exit_int_info.valid == 0)) {
  #ifdef CONFIG_DEBUG_INTERRUPTS
-       PrintDebug("Interrupt %d taken by guest\n", info->intr_state.irq_vector);
+       PrintDebug("Interrupt %d taken by guest\n", info->intr_core_state.irq_vector);
  #endif
  
        // Interrupt was taken fully vectored
-       info->intr_state.irq_started = 0;
+       info->intr_core_state.irq_started = 0;
  
      } else {
  #ifdef CONFIG_DEBUG_INTERRUPTS
@@@ -348,12 -349,12 +349,12 @@@ static int update_irq_entry_state(struc
  #endif
  
        v3_injecting_excp(info, excp);
-     } else if (info->intr_state.irq_started == 1) {
+     } else if (info->intr_core_state.irq_started == 1) {
  #ifdef CONFIG_DEBUG_INTERRUPTS
        PrintDebug("IRQ pending from previous injection\n");
  #endif
        guest_ctrl->guest_ctrl.V_IRQ = 1;
-       guest_ctrl->guest_ctrl.V_INTR_VECTOR = info->intr_state.irq_vector;
+       guest_ctrl->guest_ctrl.V_INTR_VECTOR = info->intr_core_state.irq_vector;
        guest_ctrl->guest_ctrl.V_IGN_TPR = 1;
        guest_ctrl->guest_ctrl.V_INTR_PRIO = 0xf;
  
                           (void *)(addr_t)info->rip);
  #endif
  
-               info->intr_state.irq_pending = 1;
-               info->intr_state.irq_vector = irq;
+               info->intr_core_state.irq_pending = 1;
+               info->intr_core_state.irq_vector = irq;
                
                break;
            }
@@@ -439,7 -440,7 +440,7 @@@ int v3_svm_enter(struct guest_info * in
      guest_state->rsp = info->vm_regs.rsp;
  
  #ifdef CONFIG_SYMBIOTIC
-     if (info->sym_state.sym_call_active == 0) {
+     if (info->vm_info->sym_state.symcalls[info->cpu_id].sym_call_active == 0) {
        update_irq_entry_state(info);
      }
  #else 
      */
  
  #ifdef CONFIG_SYMBIOTIC
-     if (info->sym_state.sym_call_active == 1) {
+     if (info->vm_info->sym_state.symcalls[info->cpu_id].sym_call_active == 1) {
        if (guest_ctrl->guest_ctrl.V_IRQ == 1) {
            V3_Print("!!! Injecting Interrupt during Sym call !!!\n");
        }
  
      rdtscll(info->time_state.cached_host_tsc);
      guest_ctrl->TSC_OFFSET = info->time_state.guest_tsc - info->time_state.cached_host_tsc;
 +
 +    //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->cpu_id]);
      
 +    //V3_Print("SVM Returned: Exit Code: %x, guest_rip=%lx\n", (uint32_t)(guest_ctrl->exit_code), (unsigned long)guest_state->rip);
  
 -    v3_last_exit = (uint32_t)(guest_ctrl->exit_code);
  
 -    //  v3_print_cond("SVM Returned: Exit Code: %x\n", (uint32_t)(guest_ctrl->exit_code));
 +    v3_last_exit = (uint32_t)(guest_ctrl->exit_code);
  
      rdtscll(tmp_tsc);
  
  
  
  #ifdef CONFIG_SYMBIOTIC
-     if (info->sym_state.sym_call_active == 0) {
+     if (info->vm_info->sym_state.symcalls[info->cpu_id].sym_call_active == 0) {
        update_irq_exit_state(info);
      }
  #else
@@@ -550,7 -549,7 +551,7 @@@ int v3_start_svm_guest(struct guest_inf
      PrintDebug("Launching SVM VM (vmcb=%p)\n", (void *)info->vmm_data);
      //PrintDebugVMCB((vmcb_t*)(info->vmm_data));
      
-     info->run_state = VM_RUNNING;
+     info->vm_info->run_state = VM_RUNNING;
      rdtscll(info->yield_start_cycle);
  
  
            addr_t host_addr;
            addr_t linear_addr = 0;
            
-           info->run_state = VM_ERROR;
+           info->vm_info->run_state = VM_ERROR;
            
            V3_Print("SVM ERROR!!\n");