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.


major VMX update
[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 void vmx_save_world_ctx(struct guest_info * info, struct vmx_assist_context * ctx);
26 static void 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         vmx_save_world_ctx(info, old_ctx);
61
62         /* restore new context, vmxassist should launch the bios the first time */
63         vmx_restore_world_ctx(info, new_ctx);
64
65         vmx_info->state = VMXASSIST_ENABLED;
66
67     } else if (vmx_info->state == VMXASSIST_ENABLED) {
68         /* restore old context */
69         vmx_restore_world_ctx(info, old_ctx);
70
71         vmx_info->state = VMXASSIST_DISABLED;
72     }
73
74     return 0;
75 }
76
77
78 static void save_segment(struct v3_segment * seg, struct vmx_assist_segment * vmx_assist_seg) {
79     struct vmcs_segment tmp_seg;
80
81     memset(&tmp_seg, 0, sizeof(struct vmcs_segment));
82
83     v3_seg_to_vmxseg(seg, &tmp_seg);
84
85     vmx_assist_seg->sel = tmp_seg.selector;
86     vmx_assist_seg->limit = tmp_seg.limit;
87     vmx_assist_seg->base = tmp_seg.base;
88     vmx_assist_seg->arbytes.bytes = tmp_seg.access.val;
89 }
90
91
92 static void load_segment(struct vmx_assist_segment * vmx_assist_seg, struct v3_segment * seg)  {
93     struct vmcs_segment tmp_seg;
94
95     memset(&tmp_seg, 0, sizeof(struct vmcs_segment));
96
97     tmp_seg.selector = vmx_assist_seg->sel;
98     tmp_seg.limit = vmx_assist_seg->limit;
99     tmp_seg.base = vmx_assist_seg->base;
100     tmp_seg.access.val = vmx_assist_seg->arbytes.bytes;
101
102     v3_vmxseg_to_seg(&tmp_seg, seg);
103 }
104
105 static void vmx_save_world_ctx(struct guest_info * info, struct vmx_assist_context * ctx) {
106     struct vmx_data * vmx_info = (struct vmx_data *)(info->vmm_data);
107
108     PrintDebug("Writing from RIP: 0x%p\n", (void *)info->rip);
109     
110     ctx->eip = info->rip;
111     ctx->esp = info->vm_regs.rsp;
112     ctx->eflags = info->ctrl_regs.rflags;
113
114     ctx->cr0 = info->shdw_pg_state.guest_cr0;
115     ctx->cr3 = info->shdw_pg_state.guest_cr3;
116     ctx->cr4 = vmx_info->guest_cr4;
117
118     
119     save_segment(&(info->segments.cs), &(ctx->cs));
120     save_segment(&(info->segments.ds), &(ctx->ds));
121     save_segment(&(info->segments.es), &(ctx->es));
122     save_segment(&(info->segments.ss), &(ctx->ss));
123     save_segment(&(info->segments.fs), &(ctx->fs));
124     save_segment(&(info->segments.gs), &(ctx->gs));
125     save_segment(&(info->segments.tr), &(ctx->tr));
126     save_segment(&(info->segments.ldtr), &(ctx->ldtr));
127
128     // Odd segments 
129     ctx->idtr_limit = info->segments.idtr.limit;
130     ctx->idtr_base = info->segments.idtr.base;
131
132     ctx->gdtr_limit = info->segments.gdtr.limit;
133     ctx->gdtr_base = info->segments.gdtr.base;
134 }
135
136 static void vmx_restore_world_ctx(struct guest_info * info, struct vmx_assist_context * ctx) {
137     struct vmx_data * vmx_info = (struct vmx_data *)(info->vmm_data);
138
139     PrintDebug("ctx rip: %p\n", (void *)(addr_t)ctx->eip);
140     
141     info->rip = ctx->eip;
142     info->vm_regs.rsp = ctx->esp;
143     info->ctrl_regs.rflags = ctx->eflags;
144
145     info->shdw_pg_state.guest_cr0 = ctx->cr0;
146     info->shdw_pg_state.guest_cr3 = ctx->cr3;
147     vmx_info->guest_cr4 = ctx->cr4;
148
149     load_segment(&(ctx->cs), &(info->segments.cs));
150     load_segment(&(ctx->ds), &(info->segments.ds));
151     load_segment(&(ctx->es), &(info->segments.es));
152     load_segment(&(ctx->ss), &(info->segments.ss));
153     load_segment(&(ctx->fs), &(info->segments.fs));
154     load_segment(&(ctx->gs), &(info->segments.gs));
155     load_segment(&(ctx->tr), &(info->segments.tr));
156     load_segment(&(ctx->ldtr), &(info->segments.ldtr));
157
158     // odd segments
159     info->segments.idtr.limit = ctx->idtr_limit;
160     info->segments.idtr.base = ctx->idtr_base;
161
162     info->segments.gdtr.limit = ctx->gdtr_limit;
163     info->segments.gdtr.base = ctx->gdtr_base;
164
165 }
166
167