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.


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