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.


7044e9aec86312909845f1df06deee8efc3835e6
[palacios.git] / palacios / src / palacios / vmm_symcall.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, Jack Lange <jarusl@cs.northwestern.edu> 
11  * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
12  * All rights reserved.
13  *
14  * Author: Jack Lange <jarusl@cs.northwestern.edu>
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/vm_guest.h>
21 #include <palacios/vmm_symcall.h>
22 #include <palacios/vmm_symspy.h>
23 #include <palacios/vmm_msr.h>
24
25 // A succesfull symcall returns via the RET_HCALL, with the return values in registers
26 // A symcall error returns via the ERR_HCALL with the error code in rbx
27
28
29 /* Notes: We use a combination of SYSCALL and SYSENTER Semantics 
30  * SYSCALL just sets an EIP, CS/SS seg, and GS seg via swapgs
31  * the RSP is loaded via the structure pointed to by GS
32  * This is safe because it assumes that system calls are guaranteed to be made with an empty kernel stack.
33  * We cannot make that assumption with a symcall, so we have to have our own stack area somewhere.
34  * SYSTENTER does not really use the GS base MSRs, but we do to map to 64 bit kernels
35  */
36
37 #define SYMCALL_RIP_MSR 0x536
38 #define SYMCALL_RSP_MSR 0x537
39 #define SYMCALL_CS_MSR  0x538
40 #define SYMCALL_GS_MSR  0x539
41 #define SYMCALL_FS_MSR  0x540
42
43
44 static int symcall_msr_read(struct guest_info * core, uint_t msr, 
45                             struct v3_msr * dst, void * priv_data) {
46     struct v3_symcall_state * state = &(core->sym_core_state.symcall_state);
47
48     switch (msr) {
49         case SYMCALL_RIP_MSR:
50             dst->value = state->sym_call_rip;
51             break;
52         case SYMCALL_RSP_MSR:
53             dst->value = state->sym_call_rsp;
54             break;
55         case SYMCALL_CS_MSR:
56             dst->value = state->sym_call_cs;
57             break;
58         case SYMCALL_GS_MSR:
59             dst->value = state->sym_call_gs;
60             break;
61         case SYMCALL_FS_MSR:
62             dst->value = state->sym_call_fs;
63             break;
64         default:
65             return -1;
66     }
67
68     return 0;
69 }
70
71 static int symcall_msr_write(struct guest_info * core, uint_t msr, struct v3_msr src, void * priv_data) {
72     struct v3_symcall_state * state = &(core->sym_core_state.symcall_state);
73
74     switch (msr) {
75         case SYMCALL_RIP_MSR:
76             state->sym_call_rip = src.value;
77             break;
78         case SYMCALL_RSP_MSR:
79             state->sym_call_rsp = src.value;
80             break;
81         case SYMCALL_CS_MSR:
82             state->sym_call_cs = src.value;
83             break;
84         case SYMCALL_GS_MSR:
85             state->sym_call_gs = src.value;
86             break;
87         case SYMCALL_FS_MSR:
88             state->sym_call_fs = src.value;
89             break;
90         default:
91             PrintError("Invalid Symbiotic MSR write (0x%x)\n", msr);
92             return -1;
93     }
94     return 0;
95 }
96
97
98 static int sym_call_ret(struct guest_info * info, uint_t hcall_id, void * private_data);
99 static int sym_call_err(struct guest_info * info, uint_t hcall_id, void * private_data);
100
101
102
103
104 int v3_init_symcall_vm(struct v3_vm_info * vm) {
105
106     v3_hook_msr(vm, SYMCALL_RIP_MSR, symcall_msr_read, symcall_msr_write, NULL);
107     v3_hook_msr(vm, SYMCALL_RSP_MSR, symcall_msr_read, symcall_msr_write, NULL);
108     v3_hook_msr(vm, SYMCALL_CS_MSR, symcall_msr_read, symcall_msr_write, NULL);
109     v3_hook_msr(vm, SYMCALL_GS_MSR, symcall_msr_read, symcall_msr_write, NULL);
110     v3_hook_msr(vm, SYMCALL_FS_MSR, symcall_msr_read, symcall_msr_write, NULL);
111
112     v3_register_hypercall(vm, SYMCALL_RET_HCALL, sym_call_ret, NULL);
113     v3_register_hypercall(vm, SYMCALL_ERR_HCALL, sym_call_err, NULL);
114
115
116     return 0;
117 }
118
119
120
121
122
123 static int sym_call_err(struct guest_info * core, uint_t hcall_id, void * private_data) {
124     struct v3_symcall_state * state = (struct v3_symcall_state *)&(core->sym_core_state.symcall_state);
125
126     PrintError("sym call error\n");
127
128     state->sym_call_errno = (int)core->vm_regs.rbx;
129     v3_print_guest_state(core);
130     v3_print_mem_map(core->vm_info);
131
132     // clear sym flags
133     state->sym_call_error = 1;
134     state->sym_call_returned = 1;
135
136     return -1;
137 }
138
139 static int sym_call_ret(struct guest_info * core, uint_t hcall_id, void * private_data) {
140     struct v3_symcall_state * state = (struct v3_symcall_state *)&(core->sym_core_state.symcall_state);
141
142     //    PrintError("Return from sym call (ID=%x)\n", hcall_id);
143     //   v3_print_guest_state(info);
144
145     state->sym_call_returned = 1;
146
147     return 0;
148 }
149
150 static int execute_symcall(struct guest_info * core) {
151     struct v3_symcall_state * state = (struct v3_symcall_state *)&(core->sym_core_state.symcall_state);
152
153     while (state->sym_call_returned == 0) {
154         if (v3_vm_enter(core) == -1) {
155             PrintError("Error in Sym call\n");
156             return -1;
157         }
158     }
159
160     return 0;
161 }
162
163
164 //
165 // We don't handle those fancy 64 bit system segments...
166 //
167 static int translate_segment(struct guest_info * info, uint16_t selector, struct v3_segment * seg) {
168     struct v3_segment * gdt = &(info->segments.gdtr);
169     addr_t gdt_addr = 0;
170     uint16_t seg_offset = (selector & ~0x7);
171     addr_t seg_addr = 0;
172     struct gen_segment * gen_seg = NULL;
173     struct seg_selector sel;
174
175     memset(seg, 0, sizeof(struct v3_segment));
176
177     sel.value = selector;
178
179     if (sel.ti == 1) {
180         PrintError("LDT translations not supported\n");
181         return -1;
182     }
183
184     if (v3_gva_to_hva(info, gdt->base, &gdt_addr) == -1) {
185         PrintError("Unable to translate GDT address\n");
186         return -1;
187     }
188
189     seg_addr = gdt_addr + seg_offset;
190     gen_seg = (struct gen_segment *)seg_addr;
191
192     //translate
193     seg->selector = selector;
194
195     seg->limit = gen_seg->limit_hi;
196     seg->limit <<= 16;
197     seg->limit += gen_seg->limit_lo;
198
199     seg->base = gen_seg->base_hi;
200     seg->base <<= 24;
201     seg->base += gen_seg->base_lo;
202
203     if (gen_seg->granularity == 1) {
204         seg->limit <<= 12;
205         seg->limit |= 0xfff;
206     }
207
208     seg->type = gen_seg->type;
209     seg->system = gen_seg->system;
210     seg->dpl = gen_seg->dpl;
211     seg->present = gen_seg->present;
212     seg->avail = gen_seg->avail;
213     seg->long_mode = gen_seg->long_mode;
214     seg->db = gen_seg->db;
215     seg->granularity = gen_seg->granularity;
216     
217     return 0;
218 }
219
220
221
222 int v3_sym_call(struct guest_info * core, 
223                 uint64_t call_num, sym_arg_t * arg0, 
224                 sym_arg_t * arg1, sym_arg_t * arg2,
225                 sym_arg_t * arg3, sym_arg_t * arg4) {
226     struct v3_symcall_state * state = (struct v3_symcall_state *)&(core->sym_core_state.symcall_state);
227     struct v3_symspy_local_state * symspy_state = (struct v3_symspy_local_state *)&(core->sym_core_state.symspy_state);
228     struct v3_sym_cpu_context * old_ctx = (struct v3_sym_cpu_context *)&(state->old_ctx);
229     struct v3_segment sym_cs;
230     struct v3_segment sym_ss;
231     uint64_t trash_args[5] = { [0 ... 4] = 0 };
232
233     //   PrintDebug("Making Sym call\n");
234     //    v3_print_guest_state(info);
235
236     if ((symspy_state->local_page->sym_call_enabled == 0) ||
237         (symspy_state->local_page->sym_call_active == 1)) {
238         return -1;
239     }
240     
241     if (!arg0) arg0 = &trash_args[0];
242     if (!arg1) arg1 = &trash_args[1];
243     if (!arg2) arg2 = &trash_args[2];
244     if (!arg3) arg3 = &trash_args[3];
245     if (!arg4) arg4 = &trash_args[4];
246
247     // Save the old context
248     memcpy(&(old_ctx->vm_regs), &(core->vm_regs), sizeof(struct v3_gprs));
249     memcpy(&(old_ctx->cs), &(core->segments.cs), sizeof(struct v3_segment));
250     memcpy(&(old_ctx->ss), &(core->segments.ss), sizeof(struct v3_segment));
251     old_ctx->gs_base = core->segments.gs.base;
252     old_ctx->fs_base = core->segments.fs.base;
253     old_ctx->rip = core->rip;
254     old_ctx->cpl = core->cpl;
255     old_ctx->flags = core->ctrl_regs.rflags;
256
257     // Setup the sym call context
258     core->rip = state->sym_call_rip;
259     core->vm_regs.rsp = state->sym_call_rsp; // old contest rsp is saved in vm_regs
260
261     translate_segment(core, state->sym_call_cs, &sym_cs);
262     memcpy(&(core->segments.cs), &sym_cs, sizeof(struct v3_segment));
263  
264     translate_segment(core, state->sym_call_cs + 8, &sym_ss);
265     memcpy(&(core->segments.ss), &sym_ss, sizeof(struct v3_segment));
266
267     core->segments.gs.base = state->sym_call_gs;
268     core->segments.fs.base = state->sym_call_fs;
269     core->cpl = 0;
270
271     core->vm_regs.rax = call_num;
272     core->vm_regs.rbx = *arg0;
273     core->vm_regs.rcx = *arg1;
274     core->vm_regs.rdx = *arg2;
275     core->vm_regs.rsi = *arg3;
276     core->vm_regs.rdi = *arg4;
277
278     // Mark sym call as active
279     state->sym_call_active = 1;
280     state->sym_call_returned = 0;
281
282     //    PrintDebug("Sym state\n");
283     //  v3_print_guest_state(core);
284
285     // Do the sym call entry
286     if (execute_symcall(core) == -1) {
287         PrintError("SYMCALL error\n");
288         return -1;
289     }
290
291     // clear sym flags
292     state->sym_call_active = 0;
293
294     *arg0 = core->vm_regs.rbx;
295     *arg1 = core->vm_regs.rcx;
296     *arg2 = core->vm_regs.rdx;
297     *arg3 = core->vm_regs.rsi;
298     *arg4 = core->vm_regs.rdi;
299
300     // restore guest state
301     memcpy(&(core->vm_regs), &(old_ctx->vm_regs), sizeof(struct v3_gprs));
302     memcpy(&(core->segments.cs), &(old_ctx->cs), sizeof(struct v3_segment));
303     memcpy(&(core->segments.ss), &(old_ctx->ss), sizeof(struct v3_segment));
304     core->segments.gs.base = old_ctx->gs_base;
305     core->segments.fs.base = old_ctx->fs_base;
306     core->rip = old_ctx->rip;
307     core->cpl = old_ctx->cpl;
308     core->ctrl_regs.rflags = old_ctx->flags;
309
310
311
312     //    PrintError("restoring guest state\n");
313     //    v3_print_guest_state(core);
314
315     return 0;
316 }
317
318