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.


75f27746d5ed7fa0efa63b6cd053a90f86c1fd64
[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 static int vmx_save_world_ctx(struct guest_info * info, struct vmx_assist_context * ctx);
26 static int vmx_restore_world_ctx(struct guest_info * info, struct vmx_assist_context * ctx);
27
28 int v3_vmxassist_ctx_switch(struct guest_info * info) {
29     struct vmx_assist_context * old_ctx = NULL;
30     struct vmx_assist_context * new_ctx = NULL;
31     struct vmx_assist_header * hdr = NULL;
32     struct vmx_data * vmx_info = (struct vmx_data *)info->vmm_data;
33  
34
35
36     if (guest_pa_to_host_va(info, VMXASSIST_BASE, (addr_t *)&hdr) == -1) {
37         PrintError("Could not translate address for vmxassist header\n");
38         return -1;
39     }
40
41     if (hdr->magic != VMXASSIST_MAGIC) {
42         PrintError("VMXASSIST_MAGIC field is invalid\n");
43         return -1;
44     }
45
46
47     if (guest_pa_to_host_va(info, (addr_t)(hdr->old_ctx_gpa), (addr_t *)&(old_ctx)) == -1) {
48         PrintError("Could not translate address for VMXASSIST old context\n");
49         return -1;
50     }
51
52     if (guest_pa_to_host_va(info, (addr_t)(hdr->new_ctx_gpa), (addr_t *)&(new_ctx)) == -1) {
53         PrintError("Could not translate address for VMXASSIST new context\n");
54         return -1;
55     }
56
57     if (vmx_info->state == VMXASSIST_DISABLED) {
58         
59         /* Save the old Context */
60         if (vmx_save_world_ctx(info, old_ctx) != 0) {
61             PrintError("Could not save VMXASSIST world context\n");
62             return -1;
63         }
64
65         /* restore new context, vmxassist should launch the bios the first time */
66         if (vmx_restore_world_ctx(info, new_ctx) != 0) {
67             PrintError("VMXASSIST could not restore new context\n");
68             return -1;
69         }
70
71         vmx_info->state = VMXASSIST_ENABLED;
72
73     } else if (vmx_info->state == VMXASSIST_ENABLED) {
74         /* restore old context */
75         if (vmx_restore_world_ctx(info, old_ctx) != 0) {
76             PrintError("VMXASSIST could not restore old context\n");
77             return -1;
78         }
79
80         vmx_info->state = VMXASSIST_DISABLED;
81     }
82
83     return 0;
84 }
85
86         
87 int vmx_save_world_ctx(struct guest_info * info, struct vmx_assist_context * ctx) {
88     int error = 0;
89
90     PrintDebug("Writing from RIP: 0x%p\n", (void *)info->rip);
91
92     error |= vmcs_read(VMCS_GUEST_RIP, &(ctx->eip));
93     error |= vmcs_read(VMCS_GUEST_RSP, &(ctx->esp));
94     error |= vmcs_read(VMCS_GUEST_RFLAGS, &(ctx->eflags));
95
96     error |= vmcs_read(VMCS_CR0_READ_SHDW, &(ctx->cr0));
97     ctx->cr3 = info->shdw_pg_state.guest_cr3;
98     error |= vmcs_read(VMCS_CR4_READ_SHDW, &(ctx->cr4));
99
100     error |= vmcs_read(VMCS_GUEST_IDTR_LIMIT, &(ctx->idtr_limit));
101     error |= vmcs_read(VMCS_GUEST_IDTR_BASE, &(ctx->idtr_base));
102
103     error |= vmcs_read(VMCS_GUEST_GDTR_LIMIT, &(ctx->gdtr_limit));
104     error |= vmcs_read(VMCS_GUEST_GDTR_BASE, &(ctx->gdtr_base));
105
106     error |= vmcs_read(VMCS_GUEST_CS_SELECTOR, &(ctx->cs_sel));
107     error |= vmcs_read(VMCS_GUEST_CS_LIMIT, &(ctx->cs_limit));
108     error |= vmcs_read(VMCS_GUEST_CS_BASE, &(ctx->cs_base));
109     error |= vmcs_read(VMCS_GUEST_CS_ACCESS, &(ctx->cs_arbytes.bytes));
110
111     error |= vmcs_read(VMCS_GUEST_DS_SELECTOR, &(ctx->ds_sel));
112     error |= vmcs_read(VMCS_GUEST_DS_LIMIT, &(ctx->ds_limit));
113     error |= vmcs_read(VMCS_GUEST_DS_BASE, &(ctx->ds_base));
114     error |= vmcs_read(VMCS_GUEST_DS_ACCESS, &(ctx->ds_arbytes.bytes));
115
116     error |= vmcs_read(VMCS_GUEST_ES_SELECTOR, &(ctx->es_sel));
117     error |= vmcs_read(VMCS_GUEST_ES_LIMIT, &(ctx->es_limit));
118     error |= vmcs_read(VMCS_GUEST_ES_BASE, &(ctx->es_base));
119     error |= vmcs_read(VMCS_GUEST_ES_ACCESS, &(ctx->es_arbytes.bytes));
120
121     error |= vmcs_read(VMCS_GUEST_SS_SELECTOR, &(ctx->ss_sel));
122     error |= vmcs_read(VMCS_GUEST_SS_LIMIT, &(ctx->ss_limit));
123     error |= vmcs_read(VMCS_GUEST_SS_BASE, &(ctx->ss_base));
124     error |= vmcs_read(VMCS_GUEST_SS_ACCESS, &(ctx->ss_arbytes.bytes));
125
126     error |= vmcs_read(VMCS_GUEST_FS_SELECTOR, &(ctx->fs_sel));
127     error |= vmcs_read(VMCS_GUEST_FS_LIMIT, &(ctx->fs_limit));
128     error |= vmcs_read(VMCS_GUEST_FS_BASE, &(ctx->fs_base));
129     error |= vmcs_read(VMCS_GUEST_FS_ACCESS, &(ctx->fs_arbytes.bytes));
130
131     error |= vmcs_read(VMCS_GUEST_GS_SELECTOR, &(ctx->gs_sel));
132     error |= vmcs_read(VMCS_GUEST_GS_LIMIT, &(ctx->gs_limit));
133     error |= vmcs_read(VMCS_GUEST_GS_BASE, &(ctx->gs_base));
134     error |= vmcs_read(VMCS_GUEST_GS_ACCESS, &(ctx->gs_arbytes.bytes));
135
136     error |= vmcs_read(VMCS_GUEST_TR_SELECTOR, &(ctx->tr_sel));
137     error |= vmcs_read(VMCS_GUEST_TR_LIMIT, &(ctx->tr_limit));
138     error |= vmcs_read(VMCS_GUEST_TR_BASE, &(ctx->tr_base));
139     error |= vmcs_read(VMCS_GUEST_TR_ACCESS, &(ctx->tr_arbytes.bytes));
140
141     error |= vmcs_read(VMCS_GUEST_LDTR_SELECTOR, &(ctx->ldtr_sel));
142     error |= vmcs_read(VMCS_GUEST_LDTR_LIMIT, &(ctx->ldtr_limit));
143     error |= vmcs_read(VMCS_GUEST_LDTR_BASE, &(ctx->ldtr_base));
144     error |= vmcs_read(VMCS_GUEST_LDTR_ACCESS, &(ctx->ldtr_arbytes.bytes));
145
146     return error;
147 }
148
149 int vmx_restore_world_ctx(struct guest_info * info, struct vmx_assist_context * ctx) {
150     int error = 0;
151
152     PrintDebug("ctx rip: %p\n", (void *)(addr_t)ctx->eip);
153
154     error |= vmcs_write(VMCS_GUEST_RIP, ctx->eip);
155     error |= vmcs_write(VMCS_GUEST_RSP, ctx->esp);
156     error |= vmcs_write(VMCS_GUEST_RFLAGS, ctx->eflags);
157
158     error |= vmcs_write(VMCS_CR0_READ_SHDW, ctx->cr0);
159     info->shdw_pg_state.guest_cr3 = ctx->cr3;
160     error |= vmcs_write(VMCS_CR4_READ_SHDW, ctx->cr4);
161
162     error |= vmcs_write(VMCS_GUEST_IDTR_LIMIT, ctx->idtr_limit);
163     error |= vmcs_write(VMCS_GUEST_IDTR_BASE, ctx->idtr_base);
164
165     error |= vmcs_write(VMCS_GUEST_GDTR_LIMIT, ctx->gdtr_limit);
166     error |= vmcs_write(VMCS_GUEST_GDTR_BASE, ctx->gdtr_base);
167
168     error |= vmcs_write(VMCS_GUEST_CS_SELECTOR, ctx->cs_sel);
169     error |= vmcs_write(VMCS_GUEST_CS_LIMIT, ctx->cs_limit);
170     error |= vmcs_write(VMCS_GUEST_CS_BASE, ctx->cs_base);
171     error |= vmcs_write(VMCS_GUEST_CS_ACCESS, ctx->cs_arbytes.bytes);
172
173     error |= vmcs_write(VMCS_GUEST_DS_SELECTOR, ctx->ds_sel);
174     error |= vmcs_write(VMCS_GUEST_DS_LIMIT, ctx->ds_limit);
175     error |= vmcs_write(VMCS_GUEST_DS_BASE, ctx->ds_base);
176     error |= vmcs_write(VMCS_GUEST_DS_ACCESS, ctx->ds_arbytes.bytes);
177
178     error |= vmcs_write(VMCS_GUEST_ES_SELECTOR, ctx->es_sel);
179     error |= vmcs_write(VMCS_GUEST_ES_LIMIT, ctx->es_limit);
180     error |= vmcs_write(VMCS_GUEST_ES_BASE, ctx->es_base);
181     error |= vmcs_write(VMCS_GUEST_ES_ACCESS, ctx->es_arbytes.bytes);
182
183     error |= vmcs_write(VMCS_GUEST_SS_SELECTOR, ctx->ss_sel);
184     error |= vmcs_write(VMCS_GUEST_SS_LIMIT, ctx->ss_limit);
185     error |= vmcs_write(VMCS_GUEST_SS_BASE, ctx->ss_base);
186     error |= vmcs_write(VMCS_GUEST_SS_ACCESS, ctx->ss_arbytes.bytes);
187
188     error |= vmcs_write(VMCS_GUEST_FS_SELECTOR, ctx->fs_sel);
189     error |= vmcs_write(VMCS_GUEST_FS_LIMIT, ctx->fs_limit);
190     error |= vmcs_write(VMCS_GUEST_FS_BASE, ctx->fs_base);
191     error |= vmcs_write(VMCS_GUEST_FS_ACCESS, ctx->fs_arbytes.bytes);
192
193     error |= vmcs_write(VMCS_GUEST_GS_SELECTOR, ctx->gs_sel);
194     error |= vmcs_write(VMCS_GUEST_GS_LIMIT, ctx->gs_limit);
195     error |= vmcs_write(VMCS_GUEST_GS_BASE, ctx->gs_base);
196     error |= vmcs_write(VMCS_GUEST_GS_ACCESS, ctx->gs_arbytes.bytes);
197
198     error |= vmcs_write(VMCS_GUEST_TR_SELECTOR, ctx->tr_sel);
199     error |= vmcs_write(VMCS_GUEST_TR_LIMIT, ctx->tr_limit);
200     error |= vmcs_write(VMCS_GUEST_TR_BASE, ctx->tr_base);
201     error |= vmcs_write(VMCS_GUEST_TR_ACCESS, ctx->tr_arbytes.bytes);
202
203     error |= vmcs_write(VMCS_GUEST_LDTR_SELECTOR, ctx->ldtr_sel);
204     error |= vmcs_write(VMCS_GUEST_LDTR_LIMIT, ctx->ldtr_limit);
205     error |= vmcs_write(VMCS_GUEST_LDTR_BASE, ctx->ldtr_base);
206     error |= vmcs_write(VMCS_GUEST_LDTR_ACCESS, ctx->ldtr_arbytes.bytes);
207
208     return error;
209 }
210
211