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.


Start at support for multiple VMs per core on VMX systems. Minor compile fixup for...
[palacios.git] / palacios / src / palacios / vmx_assist.c
1 /*
2  * This file is part of the Palacios Virtual Machine Monitor developed
3  * by the V3VEE Project with funding from the United States National 
4  * Science Foundation and the Department of Energy.  
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at 
8  * http://www.v3vee.org
9  *
10  * Copyright (c) 2008, Andy Gocke <agocke@gmail.com>
11  * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
12  * All rights reserved.
13  *
14  * Author: Andy Gocke <agocke@gmail.com>
15  *
16  * This is free software.  You are permitted to use,
17  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
18  */
19
20 #include <palacios/vmx_assist.h>
21 #include <palacios/vmx_lowlevel.h>
22 #include <palacios/vm_guest_mem.h>
23 #include <palacios/vmx.h>
24
25 #ifndef CONFIG_DEBUG_VMX
26 #undef PrintDebug
27 #define PrintDebug(fmt, args...)
28 #endif
29
30 static void vmx_save_world_ctx(struct guest_info * info, struct vmx_assist_context * ctx);
31 static void vmx_restore_world_ctx(struct guest_info * info, struct vmx_assist_context * ctx);
32
33 int v3_vmxassist_ctx_switch(struct guest_info * info) {
34     struct vmx_assist_context * old_ctx = NULL;
35     struct vmx_assist_context * new_ctx = NULL;
36     struct vmx_assist_header * hdr = NULL;
37     struct vmx_data * vmx_info = (struct vmx_data *)info->vmm_data;
38  
39
40
41     if (v3_gpa_to_hva(info, VMXASSIST_BASE, (addr_t *)&hdr) == -1) {
42         PrintError("Could not translate address for vmxassist header\n");
43         return -1;
44     }
45
46     if (hdr->magic != VMXASSIST_MAGIC) {
47         PrintError("VMXASSIST_MAGIC field is invalid\n");
48         return -1;
49     }
50
51
52     if (v3_gpa_to_hva(info, (addr_t)(hdr->old_ctx_gpa), (addr_t *)&(old_ctx)) == -1) {
53         PrintError("Could not translate address for VMXASSIST old context\n");
54         return -1;
55     }
56
57     if (v3_gpa_to_hva(info, (addr_t)(hdr->new_ctx_gpa), (addr_t *)&(new_ctx)) == -1) {
58         PrintError("Could not translate address for VMXASSIST new context\n");
59         return -1;
60     }
61
62     if (vmx_info->assist_state == VMXASSIST_DISABLED) {
63         
64         /* Save the old Context */
65         vmx_save_world_ctx(info, old_ctx);
66
67         /* restore new context, vmxassist should launch the bios the first time */
68         vmx_restore_world_ctx(info, new_ctx);
69
70         vmx_info->assist_state = VMXASSIST_ENABLED;
71
72     } else if (vmx_info->assist_state == VMXASSIST_ENABLED) {
73         /* restore old context */
74         vmx_restore_world_ctx(info, old_ctx);
75
76         vmx_info->assist_state = VMXASSIST_DISABLED;
77     }
78
79     return 0;
80 }
81
82
83 static void save_segment(struct v3_segment * seg, struct vmx_assist_segment * vmx_assist_seg) {
84     struct vmcs_segment tmp_seg;
85
86     memset(&tmp_seg, 0, sizeof(struct vmcs_segment));
87
88     v3_seg_to_vmxseg(seg, &tmp_seg);
89
90     vmx_assist_seg->sel = tmp_seg.selector;
91     vmx_assist_seg->limit = tmp_seg.limit;
92     vmx_assist_seg->base = tmp_seg.base;
93     vmx_assist_seg->arbytes.bytes = tmp_seg.access.val;
94 }
95
96
97 static void load_segment(struct vmx_assist_segment * vmx_assist_seg, struct v3_segment * seg)  {
98     struct vmcs_segment tmp_seg;
99
100     memset(&tmp_seg, 0, sizeof(struct vmcs_segment));
101
102     tmp_seg.selector = vmx_assist_seg->sel;
103     tmp_seg.limit = vmx_assist_seg->limit;
104     tmp_seg.base = vmx_assist_seg->base;
105     tmp_seg.access.val = vmx_assist_seg->arbytes.bytes;
106
107     v3_vmxseg_to_seg(&tmp_seg, seg);
108 }
109
110 static void vmx_save_world_ctx(struct guest_info * info, struct vmx_assist_context * ctx) {
111     struct vmx_data * vmx_info = (struct vmx_data *)(info->vmm_data);
112
113     PrintDebug("Writing from RIP: 0x%p\n", (void *)(addr_t)info->rip);
114     
115     ctx->eip = info->rip;
116     ctx->esp = info->vm_regs.rsp;
117     ctx->eflags = info->ctrl_regs.rflags;
118
119     ctx->cr0 = info->shdw_pg_state.guest_cr0;
120     ctx->cr3 = info->shdw_pg_state.guest_cr3;
121     ctx->cr4 = vmx_info->guest_cr4;
122
123     
124     save_segment(&(info->segments.cs), &(ctx->cs));
125     save_segment(&(info->segments.ds), &(ctx->ds));
126     save_segment(&(info->segments.es), &(ctx->es));
127     save_segment(&(info->segments.ss), &(ctx->ss));
128     save_segment(&(info->segments.fs), &(ctx->fs));
129     save_segment(&(info->segments.gs), &(ctx->gs));
130     save_segment(&(info->segments.tr), &(ctx->tr));
131     save_segment(&(info->segments.ldtr), &(ctx->ldtr));
132
133     // Odd segments 
134     ctx->idtr_limit = info->segments.idtr.limit;
135     ctx->idtr_base = info->segments.idtr.base;
136
137     ctx->gdtr_limit = info->segments.gdtr.limit;
138     ctx->gdtr_base = info->segments.gdtr.base;
139 }
140
141 static void vmx_restore_world_ctx(struct guest_info * info, struct vmx_assist_context * ctx) {
142     struct vmx_data * vmx_info = (struct vmx_data *)(info->vmm_data);
143
144     PrintDebug("ctx rip: %p\n", (void *)(addr_t)ctx->eip);
145     
146     info->rip = ctx->eip;
147     info->vm_regs.rsp = ctx->esp;
148     info->ctrl_regs.rflags = ctx->eflags;
149
150     info->shdw_pg_state.guest_cr0 = ctx->cr0;
151     info->shdw_pg_state.guest_cr3 = ctx->cr3;
152     vmx_info->guest_cr4 = ctx->cr4;
153
154     load_segment(&(ctx->cs), &(info->segments.cs));
155     load_segment(&(ctx->ds), &(info->segments.ds));
156     load_segment(&(ctx->es), &(info->segments.es));
157     load_segment(&(ctx->ss), &(info->segments.ss));
158     load_segment(&(ctx->fs), &(info->segments.fs));
159     load_segment(&(ctx->gs), &(info->segments.gs));
160     load_segment(&(ctx->tr), &(info->segments.tr));
161     load_segment(&(ctx->ldtr), &(info->segments.ldtr));
162
163     // odd segments
164     info->segments.idtr.limit = ctx->idtr_limit;
165     info->segments.idtr.base = ctx->idtr_base;
166
167     info->segments.gdtr.limit = ctx->gdtr_limit;
168     info->segments.gdtr.base = ctx->gdtr_base;
169
170 }
171
172