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.


bug fix to check for illegal memory ranges
[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 int v3_sym_call(struct guest_info * core, 
165                 uint64_t call_num, sym_arg_t * arg0, 
166                 sym_arg_t * arg1, sym_arg_t * arg2,
167                 sym_arg_t * arg3, sym_arg_t * arg4) {
168     struct v3_symcall_state * state = (struct v3_symcall_state *)&(core->sym_core_state.symcall_state);
169     struct v3_symspy_local_state * symspy_state = (struct v3_symspy_local_state *)&(core->sym_core_state.symspy_state);
170     struct v3_sym_cpu_context * old_ctx = (struct v3_sym_cpu_context *)&(state->old_ctx);
171     struct v3_segment sym_cs;
172     struct v3_segment sym_ss;
173     uint64_t trash_args[5] = { [0 ... 4] = 0 };
174
175     //   PrintDebug("Making Sym call\n");
176     //    v3_print_guest_state(info);
177
178     if ((symspy_state->local_page->sym_call_enabled == 0) ||
179         (symspy_state->local_page->sym_call_active == 1)) {
180         return -1;
181     }
182     
183     if (!arg0) arg0 = &trash_args[0];
184     if (!arg1) arg1 = &trash_args[1];
185     if (!arg2) arg2 = &trash_args[2];
186     if (!arg3) arg3 = &trash_args[3];
187     if (!arg4) arg4 = &trash_args[4];
188
189     // Save the old context
190     memcpy(&(old_ctx->vm_regs), &(core->vm_regs), sizeof(struct v3_gprs));
191     memcpy(&(old_ctx->cs), &(core->segments.cs), sizeof(struct v3_segment));
192     memcpy(&(old_ctx->ss), &(core->segments.ss), sizeof(struct v3_segment));
193     old_ctx->gs_base = core->segments.gs.base;
194     old_ctx->fs_base = core->segments.fs.base;
195     old_ctx->rip = core->rip;
196     old_ctx->cpl = core->cpl;
197     old_ctx->flags = core->ctrl_regs.rflags;
198
199     // Setup the sym call context
200     core->rip = state->sym_call_rip;
201     core->vm_regs.rsp = state->sym_call_rsp; // old contest rsp is saved in vm_regs
202
203     v3_translate_segment(core, state->sym_call_cs, &sym_cs);
204     memcpy(&(core->segments.cs), &sym_cs, sizeof(struct v3_segment));
205  
206     v3_translate_segment(core, state->sym_call_cs + 8, &sym_ss);
207     memcpy(&(core->segments.ss), &sym_ss, sizeof(struct v3_segment));
208
209     core->segments.gs.base = state->sym_call_gs;
210     core->segments.fs.base = state->sym_call_fs;
211     core->cpl = 0;
212
213     core->vm_regs.rax = call_num;
214     core->vm_regs.rbx = *arg0;
215     core->vm_regs.rcx = *arg1;
216     core->vm_regs.rdx = *arg2;
217     core->vm_regs.rsi = *arg3;
218     core->vm_regs.rdi = *arg4;
219
220     // Mark sym call as active
221     state->sym_call_active = 1;
222     state->sym_call_returned = 0;
223
224     //    PrintDebug("Sym state\n");
225     //  v3_print_guest_state(core);
226
227     // Do the sym call entry
228     if (execute_symcall(core) == -1) {
229         PrintError("SYMCALL error\n");
230         return -1;
231     }
232
233     // clear sym flags
234     state->sym_call_active = 0;
235
236     *arg0 = core->vm_regs.rbx;
237     *arg1 = core->vm_regs.rcx;
238     *arg2 = core->vm_regs.rdx;
239     *arg3 = core->vm_regs.rsi;
240     *arg4 = core->vm_regs.rdi;
241
242     // restore guest state
243     memcpy(&(core->vm_regs), &(old_ctx->vm_regs), sizeof(struct v3_gprs));
244     memcpy(&(core->segments.cs), &(old_ctx->cs), sizeof(struct v3_segment));
245     memcpy(&(core->segments.ss), &(old_ctx->ss), sizeof(struct v3_segment));
246     core->segments.gs.base = old_ctx->gs_base;
247     core->segments.fs.base = old_ctx->fs_base;
248     core->rip = old_ctx->rip;
249     core->cpl = old_ctx->cpl;
250     core->ctrl_regs.rflags = old_ctx->flags;
251
252
253
254     //    PrintError("restoring guest state\n");
255     //    v3_print_guest_state(core);
256
257     return 0;
258 }
259
260