1 | /* |
---|
2 | * svm.c: handling SVM architecture-related VM exits |
---|
3 | * Copyright (c) 2004, Intel Corporation. |
---|
4 | * Copyright (c) 2005, AMD Corporation. |
---|
5 | * |
---|
6 | * This program is free software; you can redistribute it and/or modify it |
---|
7 | * under the terms and conditions of the GNU General Public License, |
---|
8 | * version 2, as published by the Free Software Foundation. |
---|
9 | * |
---|
10 | * This program is distributed in the hope it will be useful, but WITHOUT |
---|
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
---|
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
---|
13 | * more details. |
---|
14 | * |
---|
15 | * You should have received a copy of the GNU General Public License along with |
---|
16 | * this program; if not, write to the Free Software Foundation, Inc., 59 Temple |
---|
17 | * Place - Suite 330, Boston, MA 02111-1307 USA. |
---|
18 | */ |
---|
19 | |
---|
20 | #include <xen/config.h> |
---|
21 | #include <xen/init.h> |
---|
22 | #include <xen/lib.h> |
---|
23 | #include <xen/trace.h> |
---|
24 | #include <xen/sched.h> |
---|
25 | #include <xen/irq.h> |
---|
26 | #include <xen/softirq.h> |
---|
27 | #include <xen/hypercall.h> |
---|
28 | #include <xen/domain_page.h> |
---|
29 | #include <asm/current.h> |
---|
30 | #include <asm/io.h> |
---|
31 | #include <asm/paging.h> |
---|
32 | #include <asm/p2m.h> |
---|
33 | #include <asm/regs.h> |
---|
34 | #include <asm/cpufeature.h> |
---|
35 | #include <asm/processor.h> |
---|
36 | #include <asm/types.h> |
---|
37 | #include <asm/msr.h> |
---|
38 | #include <asm/spinlock.h> |
---|
39 | #include <asm/hvm/hvm.h> |
---|
40 | #include <asm/hvm/support.h> |
---|
41 | #include <asm/hvm/io.h> |
---|
42 | #include <asm/hvm/svm/svm.h> |
---|
43 | #include <asm/hvm/svm/vmcb.h> |
---|
44 | #include <asm/hvm/svm/emulate.h> |
---|
45 | #include <asm/hvm/svm/intr.h> |
---|
46 | #include <asm/x86_emulate.h> |
---|
47 | #include <public/sched.h> |
---|
48 | #include <asm/hvm/vpt.h> |
---|
49 | #include <asm/hvm/trace.h> |
---|
50 | #include <asm/hap.h> |
---|
51 | |
---|
52 | #define set_segment_register(name, value) \ |
---|
53 | asm volatile ( "movw %%ax ,%%" STR(name) "" : : "a" (value) ) |
---|
54 | |
---|
55 | int inst_copy_from_guest(unsigned char *buf, unsigned long guest_eip, |
---|
56 | int inst_len); |
---|
57 | asmlinkage void do_IRQ(struct cpu_user_regs *); |
---|
58 | |
---|
59 | static int svm_reset_to_realmode(struct vcpu *v, |
---|
60 | struct cpu_user_regs *regs); |
---|
61 | |
---|
62 | /* va of hardware host save area */ |
---|
63 | static void *hsa[NR_CPUS] __read_mostly; |
---|
64 | |
---|
65 | /* vmcb used for extended host state */ |
---|
66 | static void *root_vmcb[NR_CPUS] __read_mostly; |
---|
67 | |
---|
68 | /* physical address of above for host VMSAVE/VMLOAD */ |
---|
69 | u64 root_vmcb_pa[NR_CPUS] __read_mostly; |
---|
70 | |
---|
71 | /* hardware assisted paging bits */ |
---|
72 | extern int opt_hap_enabled; |
---|
73 | |
---|
74 | static inline void svm_inject_exception(struct vcpu *v, int trap, |
---|
75 | int ev, int error_code) |
---|
76 | { |
---|
77 | eventinj_t event; |
---|
78 | struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; |
---|
79 | |
---|
80 | if ( trap == TRAP_page_fault ) |
---|
81 | HVMTRACE_2D(PF_INJECT, v, v->arch.hvm_svm.cpu_cr2, error_code); |
---|
82 | else |
---|
83 | HVMTRACE_2D(INJ_EXC, v, trap, error_code); |
---|
84 | |
---|
85 | event.bytes = 0; |
---|
86 | event.fields.v = 1; |
---|
87 | event.fields.type = EVENTTYPE_EXCEPTION; |
---|
88 | event.fields.vector = trap; |
---|
89 | event.fields.ev = ev; |
---|
90 | event.fields.errorcode = error_code; |
---|
91 | |
---|
92 | ASSERT(vmcb->eventinj.fields.v == 0); |
---|
93 | |
---|
94 | vmcb->eventinj = event; |
---|
95 | } |
---|
96 | |
---|
97 | static void stop_svm(void) |
---|
98 | { |
---|
99 | u32 eax, edx; |
---|
100 | /* We turn off the EFER_SVME bit. */ |
---|
101 | rdmsr(MSR_EFER, eax, edx); |
---|
102 | eax &= ~EFER_SVME; |
---|
103 | wrmsr(MSR_EFER, eax, edx); |
---|
104 | } |
---|
105 | |
---|
106 | static void svm_store_cpu_guest_regs( |
---|
107 | struct vcpu *v, struct cpu_user_regs *regs, unsigned long *crs) |
---|
108 | { |
---|
109 | struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; |
---|
110 | |
---|
111 | if ( regs != NULL ) |
---|
112 | { |
---|
113 | regs->eip = vmcb->rip; |
---|
114 | regs->esp = vmcb->rsp; |
---|
115 | regs->eflags = vmcb->rflags; |
---|
116 | regs->cs = vmcb->cs.sel; |
---|
117 | regs->ds = vmcb->ds.sel; |
---|
118 | regs->es = vmcb->es.sel; |
---|
119 | regs->ss = vmcb->ss.sel; |
---|
120 | regs->gs = vmcb->gs.sel; |
---|
121 | regs->fs = vmcb->fs.sel; |
---|
122 | } |
---|
123 | |
---|
124 | if ( crs != NULL ) |
---|
125 | { |
---|
126 | /* Returning the guest's regs */ |
---|
127 | crs[0] = v->arch.hvm_svm.cpu_shadow_cr0; |
---|
128 | crs[2] = v->arch.hvm_svm.cpu_cr2; |
---|
129 | crs[3] = v->arch.hvm_svm.cpu_cr3; |
---|
130 | crs[4] = v->arch.hvm_svm.cpu_shadow_cr4; |
---|
131 | } |
---|
132 | } |
---|
133 | |
---|
134 | static inline int long_mode_do_msr_write(struct cpu_user_regs *regs) |
---|
135 | { |
---|
136 | u64 msr_content = (u32)regs->eax | ((u64)regs->edx << 32); |
---|
137 | u32 ecx = regs->ecx; |
---|
138 | struct vcpu *v = current; |
---|
139 | struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; |
---|
140 | |
---|
141 | HVM_DBG_LOG(DBG_LEVEL_1, "msr %x msr_content %"PRIx64"\n", |
---|
142 | ecx, msr_content); |
---|
143 | |
---|
144 | switch ( ecx ) |
---|
145 | { |
---|
146 | case MSR_EFER: |
---|
147 | /* Offending reserved bit will cause #GP. */ |
---|
148 | if ( msr_content & ~(EFER_LME | EFER_LMA | EFER_NX | EFER_SCE) ) |
---|
149 | { |
---|
150 | gdprintk(XENLOG_WARNING, "Trying to set reserved bit in " |
---|
151 | "EFER: %"PRIx64"\n", msr_content); |
---|
152 | goto gp_fault; |
---|
153 | } |
---|
154 | |
---|
155 | #ifdef __x86_64__ |
---|
156 | if ( (msr_content & EFER_LME) && !svm_lme_is_set(v) ) |
---|
157 | { |
---|
158 | /* EFER.LME transition from 0 to 1. */ |
---|
159 | if ( svm_paging_enabled(v) || !svm_cr4_pae_is_set(v) ) |
---|
160 | { |
---|
161 | gdprintk(XENLOG_WARNING, "Trying to set LME bit when " |
---|
162 | "in paging mode or PAE bit is not set\n"); |
---|
163 | goto gp_fault; |
---|
164 | } |
---|
165 | } |
---|
166 | else if ( !(msr_content & EFER_LME) && svm_lme_is_set(v) ) |
---|
167 | { |
---|
168 | /* EFER.LME transistion from 1 to 0. */ |
---|
169 | if ( svm_paging_enabled(v) ) |
---|
170 | { |
---|
171 | gdprintk(XENLOG_WARNING, |
---|
172 | "Trying to clear EFER.LME while paging enabled\n"); |
---|
173 | goto gp_fault; |
---|
174 | } |
---|
175 | } |
---|
176 | #endif /* __x86_64__ */ |
---|
177 | |
---|
178 | v->arch.hvm_svm.cpu_shadow_efer = msr_content; |
---|
179 | vmcb->efer = msr_content | EFER_SVME; |
---|
180 | if ( !svm_paging_enabled(v) ) |
---|
181 | vmcb->efer &= ~(EFER_LME | EFER_LMA); |
---|
182 | |
---|
183 | break; |
---|
184 | |
---|
185 | default: |
---|
186 | return 0; |
---|
187 | } |
---|
188 | |
---|
189 | return 1; |
---|
190 | |
---|
191 | gp_fault: |
---|
192 | svm_inject_exception(v, TRAP_gp_fault, 1, 0); |
---|
193 | return 0; |
---|
194 | } |
---|
195 | |
---|
196 | |
---|
197 | #define loaddebug(_v,_reg) \ |
---|
198 | asm volatile ("mov %0,%%db" #_reg : : "r" ((_v)->debugreg[_reg])) |
---|
199 | #define savedebug(_v,_reg) \ |
---|
200 | asm volatile ("mov %%db" #_reg ",%0" : : "r" ((_v)->debugreg[_reg])) |
---|
201 | |
---|
202 | static inline void svm_save_dr(struct vcpu *v) |
---|
203 | { |
---|
204 | struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; |
---|
205 | |
---|
206 | if ( !v->arch.hvm_vcpu.flag_dr_dirty ) |
---|
207 | return; |
---|
208 | |
---|
209 | /* Clear the DR dirty flag and re-enable intercepts for DR accesses. */ |
---|
210 | v->arch.hvm_vcpu.flag_dr_dirty = 0; |
---|
211 | v->arch.hvm_svm.vmcb->dr_intercepts = DR_INTERCEPT_ALL_WRITES; |
---|
212 | |
---|
213 | savedebug(&v->arch.guest_context, 0); |
---|
214 | savedebug(&v->arch.guest_context, 1); |
---|
215 | savedebug(&v->arch.guest_context, 2); |
---|
216 | savedebug(&v->arch.guest_context, 3); |
---|
217 | v->arch.guest_context.debugreg[6] = vmcb->dr6; |
---|
218 | v->arch.guest_context.debugreg[7] = vmcb->dr7; |
---|
219 | } |
---|
220 | |
---|
221 | |
---|
222 | static inline void __restore_debug_registers(struct vcpu *v) |
---|
223 | { |
---|
224 | loaddebug(&v->arch.guest_context, 0); |
---|
225 | loaddebug(&v->arch.guest_context, 1); |
---|
226 | loaddebug(&v->arch.guest_context, 2); |
---|
227 | loaddebug(&v->arch.guest_context, 3); |
---|
228 | /* DR6 and DR7 are loaded from the VMCB. */ |
---|
229 | } |
---|
230 | |
---|
231 | |
---|
232 | int svm_vmcb_save(struct vcpu *v, struct hvm_hw_cpu *c) |
---|
233 | { |
---|
234 | struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; |
---|
235 | |
---|
236 | c->rip = vmcb->rip; |
---|
237 | |
---|
238 | #ifdef HVM_DEBUG_SUSPEND |
---|
239 | printk("%s: eip=0x%"PRIx64".\n", |
---|
240 | __func__, |
---|
241 | inst_len, c->eip); |
---|
242 | #endif |
---|
243 | |
---|
244 | c->rsp = vmcb->rsp; |
---|
245 | c->rflags = vmcb->rflags; |
---|
246 | |
---|
247 | c->cr0 = v->arch.hvm_svm.cpu_shadow_cr0; |
---|
248 | c->cr2 = v->arch.hvm_svm.cpu_cr2; |
---|
249 | c->cr3 = v->arch.hvm_svm.cpu_cr3; |
---|
250 | c->cr4 = v->arch.hvm_svm.cpu_shadow_cr4; |
---|
251 | |
---|
252 | #ifdef HVM_DEBUG_SUSPEND |
---|
253 | printk("%s: cr3=0x%"PRIx64", cr0=0x%"PRIx64", cr4=0x%"PRIx64".\n", |
---|
254 | __func__, |
---|
255 | c->cr3, |
---|
256 | c->cr0, |
---|
257 | c->cr4); |
---|
258 | #endif |
---|
259 | |
---|
260 | c->idtr_limit = vmcb->idtr.limit; |
---|
261 | c->idtr_base = vmcb->idtr.base; |
---|
262 | |
---|
263 | c->gdtr_limit = vmcb->gdtr.limit; |
---|
264 | c->gdtr_base = vmcb->gdtr.base; |
---|
265 | |
---|
266 | c->cs_sel = vmcb->cs.sel; |
---|
267 | c->cs_limit = vmcb->cs.limit; |
---|
268 | c->cs_base = vmcb->cs.base; |
---|
269 | c->cs_arbytes = vmcb->cs.attr.bytes; |
---|
270 | |
---|
271 | c->ds_sel = vmcb->ds.sel; |
---|
272 | c->ds_limit = vmcb->ds.limit; |
---|
273 | c->ds_base = vmcb->ds.base; |
---|
274 | c->ds_arbytes = vmcb->ds.attr.bytes; |
---|
275 | |
---|
276 | c->es_sel = vmcb->es.sel; |
---|
277 | c->es_limit = vmcb->es.limit; |
---|
278 | c->es_base = vmcb->es.base; |
---|
279 | c->es_arbytes = vmcb->es.attr.bytes; |
---|
280 | |
---|
281 | c->ss_sel = vmcb->ss.sel; |
---|
282 | c->ss_limit = vmcb->ss.limit; |
---|
283 | c->ss_base = vmcb->ss.base; |
---|
284 | c->ss_arbytes = vmcb->ss.attr.bytes; |
---|
285 | |
---|
286 | c->fs_sel = vmcb->fs.sel; |
---|
287 | c->fs_limit = vmcb->fs.limit; |
---|
288 | c->fs_base = vmcb->fs.base; |
---|
289 | c->fs_arbytes = vmcb->fs.attr.bytes; |
---|
290 | |
---|
291 | c->gs_sel = vmcb->gs.sel; |
---|
292 | c->gs_limit = vmcb->gs.limit; |
---|
293 | c->gs_base = vmcb->gs.base; |
---|
294 | c->gs_arbytes = vmcb->gs.attr.bytes; |
---|
295 | |
---|
296 | c->tr_sel = vmcb->tr.sel; |
---|
297 | c->tr_limit = vmcb->tr.limit; |
---|
298 | c->tr_base = vmcb->tr.base; |
---|
299 | c->tr_arbytes = vmcb->tr.attr.bytes; |
---|
300 | |
---|
301 | c->ldtr_sel = vmcb->ldtr.sel; |
---|
302 | c->ldtr_limit = vmcb->ldtr.limit; |
---|
303 | c->ldtr_base = vmcb->ldtr.base; |
---|
304 | c->ldtr_arbytes = vmcb->ldtr.attr.bytes; |
---|
305 | |
---|
306 | c->sysenter_cs = vmcb->sysenter_cs; |
---|
307 | c->sysenter_esp = vmcb->sysenter_esp; |
---|
308 | c->sysenter_eip = vmcb->sysenter_eip; |
---|
309 | |
---|
310 | /* Save any event/interrupt that was being injected when we last |
---|
311 | * exited. Although there are three(!) VMCB fields that can contain |
---|
312 | * active events, we only need to save at most one: because the |
---|
313 | * intr_assist logic never delivers an IRQ when any other event is |
---|
314 | * active, we know that the only possible collision is if we inject |
---|
315 | * a fault while exitintinfo contains a valid event (the delivery of |
---|
316 | * which caused the last exit). In that case replaying just the |
---|
317 | * first event should cause the same behaviour when we restore. */ |
---|
318 | if ( vmcb->vintr.fields.irq |
---|
319 | && /* Check it's not a fake interrupt (see svm_intr_assist()) */ |
---|
320 | !(vmcb->general1_intercepts & GENERAL1_INTERCEPT_VINTR) ) |
---|
321 | { |
---|
322 | c->pending_vector = vmcb->vintr.fields.vector; |
---|
323 | c->pending_type = 0; /* External interrupt */ |
---|
324 | c->pending_error_valid = 0; |
---|
325 | c->pending_reserved = 0; |
---|
326 | c->pending_valid = 1; |
---|
327 | c->error_code = 0; |
---|
328 | } |
---|
329 | else if ( vmcb->exitintinfo.fields.v ) |
---|
330 | { |
---|
331 | c->pending_event = vmcb->exitintinfo.bytes & 0xffffffff; |
---|
332 | c->error_code = vmcb->exitintinfo.fields.errorcode; |
---|
333 | } |
---|
334 | else if ( vmcb->eventinj.fields.v ) |
---|
335 | { |
---|
336 | c->pending_event = vmcb->eventinj.bytes & 0xffffffff; |
---|
337 | c->error_code = vmcb->eventinj.fields.errorcode; |
---|
338 | } |
---|
339 | else |
---|
340 | { |
---|
341 | c->pending_event = 0; |
---|
342 | c->error_code = 0; |
---|
343 | } |
---|
344 | |
---|
345 | return 1; |
---|
346 | } |
---|
347 | |
---|
348 | |
---|
349 | int svm_vmcb_restore(struct vcpu *v, struct hvm_hw_cpu *c) |
---|
350 | { |
---|
351 | unsigned long mfn, old_base_mfn; |
---|
352 | struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; |
---|
353 | |
---|
354 | vmcb->rip = c->rip; |
---|
355 | vmcb->rsp = c->rsp; |
---|
356 | vmcb->rflags = c->rflags; |
---|
357 | |
---|
358 | v->arch.hvm_svm.cpu_shadow_cr0 = c->cr0; |
---|
359 | vmcb->cr0 = c->cr0 | X86_CR0_WP | X86_CR0_ET | X86_CR0_PG; |
---|
360 | |
---|
361 | v->arch.hvm_svm.cpu_cr2 = c->cr2; |
---|
362 | |
---|
363 | #ifdef HVM_DEBUG_SUSPEND |
---|
364 | printk("%s: cr3=0x%"PRIx64", cr0=0x%"PRIx64", cr4=0x%"PRIx64".\n", |
---|
365 | __func__, |
---|
366 | c->cr3, |
---|
367 | c->cr0, |
---|
368 | c->cr4); |
---|
369 | #endif |
---|
370 | |
---|
371 | if ( !svm_paging_enabled(v) ) |
---|
372 | { |
---|
373 | printk("%s: paging not enabled.\n", __func__); |
---|
374 | goto skip_cr3; |
---|
375 | } |
---|
376 | |
---|
377 | if ( c->cr3 == v->arch.hvm_svm.cpu_cr3 ) |
---|
378 | { |
---|
379 | /* |
---|
380 | * This is simple TLB flush, implying the guest has |
---|
381 | * removed some translation or changed page attributes. |
---|
382 | * We simply invalidate the shadow. |
---|
383 | */ |
---|
384 | mfn = gmfn_to_mfn(v->domain, c->cr3 >> PAGE_SHIFT); |
---|
385 | if ( mfn != pagetable_get_pfn(v->arch.guest_table) ) |
---|
386 | goto bad_cr3; |
---|
387 | } |
---|
388 | else |
---|
389 | { |
---|
390 | /* |
---|
391 | * If different, make a shadow. Check if the PDBR is valid |
---|
392 | * first. |
---|
393 | */ |
---|
394 | HVM_DBG_LOG(DBG_LEVEL_VMMU, "CR3 c->cr3 = %"PRIx64"", c->cr3); |
---|
395 | mfn = gmfn_to_mfn(v->domain, c->cr3 >> PAGE_SHIFT); |
---|
396 | if( !mfn_valid(mfn) || !get_page(mfn_to_page(mfn), v->domain) ) |
---|
397 | goto bad_cr3; |
---|
398 | |
---|
399 | old_base_mfn = pagetable_get_pfn(v->arch.guest_table); |
---|
400 | v->arch.guest_table = pagetable_from_pfn(mfn); |
---|
401 | if (old_base_mfn) |
---|
402 | put_page(mfn_to_page(old_base_mfn)); |
---|
403 | v->arch.hvm_svm.cpu_cr3 = c->cr3; |
---|
404 | } |
---|
405 | |
---|
406 | skip_cr3: |
---|
407 | vmcb->cr4 = c->cr4 | SVM_CR4_HOST_MASK; |
---|
408 | v->arch.hvm_svm.cpu_shadow_cr4 = c->cr4; |
---|
409 | |
---|
410 | vmcb->idtr.limit = c->idtr_limit; |
---|
411 | vmcb->idtr.base = c->idtr_base; |
---|
412 | |
---|
413 | vmcb->gdtr.limit = c->gdtr_limit; |
---|
414 | vmcb->gdtr.base = c->gdtr_base; |
---|
415 | |
---|
416 | vmcb->cs.sel = c->cs_sel; |
---|
417 | vmcb->cs.limit = c->cs_limit; |
---|
418 | vmcb->cs.base = c->cs_base; |
---|
419 | vmcb->cs.attr.bytes = c->cs_arbytes; |
---|
420 | |
---|
421 | vmcb->ds.sel = c->ds_sel; |
---|
422 | vmcb->ds.limit = c->ds_limit; |
---|
423 | vmcb->ds.base = c->ds_base; |
---|
424 | vmcb->ds.attr.bytes = c->ds_arbytes; |
---|
425 | |
---|
426 | vmcb->es.sel = c->es_sel; |
---|
427 | vmcb->es.limit = c->es_limit; |
---|
428 | vmcb->es.base = c->es_base; |
---|
429 | vmcb->es.attr.bytes = c->es_arbytes; |
---|
430 | |
---|
431 | vmcb->ss.sel = c->ss_sel; |
---|
432 | vmcb->ss.limit = c->ss_limit; |
---|
433 | vmcb->ss.base = c->ss_base; |
---|
434 | vmcb->ss.attr.bytes = c->ss_arbytes; |
---|
435 | vmcb->cpl = vmcb->ss.attr.fields.dpl; |
---|
436 | |
---|
437 | vmcb->fs.sel = c->fs_sel; |
---|
438 | vmcb->fs.limit = c->fs_limit; |
---|
439 | vmcb->fs.base = c->fs_base; |
---|
440 | vmcb->fs.attr.bytes = c->fs_arbytes; |
---|
441 | |
---|
442 | vmcb->gs.sel = c->gs_sel; |
---|
443 | vmcb->gs.limit = c->gs_limit; |
---|
444 | vmcb->gs.base = c->gs_base; |
---|
445 | vmcb->gs.attr.bytes = c->gs_arbytes; |
---|
446 | |
---|
447 | vmcb->tr.sel = c->tr_sel; |
---|
448 | vmcb->tr.limit = c->tr_limit; |
---|
449 | vmcb->tr.base = c->tr_base; |
---|
450 | vmcb->tr.attr.bytes = c->tr_arbytes; |
---|
451 | |
---|
452 | vmcb->ldtr.sel = c->ldtr_sel; |
---|
453 | vmcb->ldtr.limit = c->ldtr_limit; |
---|
454 | vmcb->ldtr.base = c->ldtr_base; |
---|
455 | vmcb->ldtr.attr.bytes = c->ldtr_arbytes; |
---|
456 | |
---|
457 | vmcb->sysenter_cs = c->sysenter_cs; |
---|
458 | vmcb->sysenter_esp = c->sysenter_esp; |
---|
459 | vmcb->sysenter_eip = c->sysenter_eip; |
---|
460 | |
---|
461 | /* update VMCB for nested paging restore */ |
---|
462 | if ( paging_mode_hap(v->domain) ) { |
---|
463 | vmcb->cr0 = v->arch.hvm_svm.cpu_shadow_cr0; |
---|
464 | vmcb->cr4 = v->arch.hvm_svm.cpu_shadow_cr4; |
---|
465 | vmcb->cr3 = c->cr3; |
---|
466 | vmcb->np_enable = 1; |
---|
467 | vmcb->g_pat = 0x0007040600070406ULL; /* guest PAT */ |
---|
468 | vmcb->h_cr3 = pagetable_get_paddr(v->domain->arch.phys_table); |
---|
469 | } |
---|
470 | |
---|
471 | vmcb->dr6 = c->dr6; |
---|
472 | vmcb->dr7 = c->dr7; |
---|
473 | |
---|
474 | if ( c->pending_valid ) |
---|
475 | { |
---|
476 | gdprintk(XENLOG_INFO, "Re-injecting 0x%"PRIx32", 0x%"PRIx32"\n", |
---|
477 | c->pending_event, c->error_code); |
---|
478 | |
---|
479 | /* VMX uses a different type for #OF and #BP; fold into "Exception" */ |
---|
480 | if ( c->pending_type == 6 ) |
---|
481 | c->pending_type = 3; |
---|
482 | /* Sanity check */ |
---|
483 | if ( c->pending_type == 1 || c->pending_type > 4 |
---|
484 | || c->pending_reserved != 0 ) |
---|
485 | { |
---|
486 | gdprintk(XENLOG_ERR, "Invalid pending event 0x%"PRIx32"\n", |
---|
487 | c->pending_event); |
---|
488 | return -EINVAL; |
---|
489 | } |
---|
490 | /* Put this pending event in exitintinfo and svm_intr_assist() |
---|
491 | * will reinject it when we return to the guest. */ |
---|
492 | vmcb->exitintinfo.bytes = c->pending_event; |
---|
493 | vmcb->exitintinfo.fields.errorcode = c->error_code; |
---|
494 | } |
---|
495 | |
---|
496 | paging_update_paging_modes(v); |
---|
497 | return 0; |
---|
498 | |
---|
499 | bad_cr3: |
---|
500 | gdprintk(XENLOG_ERR, "Invalid CR3 value=0x%"PRIx64"\n", c->cr3); |
---|
501 | return -EINVAL; |
---|
502 | } |
---|
503 | |
---|
504 | |
---|
505 | void svm_save_cpu_state(struct vcpu *v, struct hvm_hw_cpu *data) |
---|
506 | { |
---|
507 | struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; |
---|
508 | |
---|
509 | data->shadow_gs = vmcb->kerngsbase; |
---|
510 | data->msr_lstar = vmcb->lstar; |
---|
511 | data->msr_star = vmcb->star; |
---|
512 | data->msr_cstar = vmcb->cstar; |
---|
513 | data->msr_syscall_mask = vmcb->sfmask; |
---|
514 | data->msr_efer = v->arch.hvm_svm.cpu_shadow_efer; |
---|
515 | data->msr_flags = -1ULL; |
---|
516 | |
---|
517 | data->tsc = hvm_get_guest_time(v); |
---|
518 | } |
---|
519 | |
---|
520 | |
---|
521 | void svm_load_cpu_state(struct vcpu *v, struct hvm_hw_cpu *data) |
---|
522 | { |
---|
523 | struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; |
---|
524 | |
---|
525 | vmcb->kerngsbase = data->shadow_gs; |
---|
526 | vmcb->lstar = data->msr_lstar; |
---|
527 | vmcb->star = data->msr_star; |
---|
528 | vmcb->cstar = data->msr_cstar; |
---|
529 | vmcb->sfmask = data->msr_syscall_mask; |
---|
530 | v->arch.hvm_svm.cpu_shadow_efer = data->msr_efer; |
---|
531 | vmcb->efer = data->msr_efer | EFER_SVME; |
---|
532 | /* VMCB's EFER.LME isn't set unless we're actually in long mode |
---|
533 | * (see long_mode_do_msr_write()) */ |
---|
534 | if ( !(vmcb->efer & EFER_LMA) ) |
---|
535 | vmcb->efer &= ~EFER_LME; |
---|
536 | |
---|
537 | hvm_set_guest_time(v, data->tsc); |
---|
538 | } |
---|
539 | |
---|
540 | void svm_save_vmcb_ctxt(struct vcpu *v, struct hvm_hw_cpu *ctxt) |
---|
541 | { |
---|
542 | svm_save_cpu_state(v, ctxt); |
---|
543 | svm_vmcb_save(v, ctxt); |
---|
544 | } |
---|
545 | |
---|
546 | int svm_load_vmcb_ctxt(struct vcpu *v, struct hvm_hw_cpu *ctxt) |
---|
547 | { |
---|
548 | svm_load_cpu_state(v, ctxt); |
---|
549 | if (svm_vmcb_restore(v, ctxt)) { |
---|
550 | printk("svm_vmcb restore failed!\n"); |
---|
551 | domain_crash(v->domain); |
---|
552 | return -EINVAL; |
---|
553 | } |
---|
554 | |
---|
555 | return 0; |
---|
556 | } |
---|
557 | |
---|
558 | |
---|
559 | static inline void svm_restore_dr(struct vcpu *v) |
---|
560 | { |
---|
561 | if ( unlikely(v->arch.guest_context.debugreg[7] & 0xFF) ) |
---|
562 | __restore_debug_registers(v); |
---|
563 | } |
---|
564 | |
---|
565 | |
---|
566 | static int svm_realmode(struct vcpu *v) |
---|
567 | { |
---|
568 | unsigned long cr0 = v->arch.hvm_svm.cpu_shadow_cr0; |
---|
569 | unsigned long eflags = v->arch.hvm_svm.vmcb->rflags; |
---|
570 | |
---|
571 | return (eflags & X86_EFLAGS_VM) || !(cr0 & X86_CR0_PE); |
---|
572 | } |
---|
573 | |
---|
574 | static int svm_interrupts_enabled(struct vcpu *v) |
---|
575 | { |
---|
576 | unsigned long eflags = v->arch.hvm_svm.vmcb->rflags; |
---|
577 | return !irq_masked(eflags); |
---|
578 | } |
---|
579 | |
---|
580 | static int svm_guest_x86_mode(struct vcpu *v) |
---|
581 | { |
---|
582 | struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; |
---|
583 | |
---|
584 | if ( svm_long_mode_enabled(v) && vmcb->cs.attr.fields.l ) |
---|
585 | return 8; |
---|
586 | |
---|
587 | if ( svm_realmode(v) ) |
---|
588 | return 2; |
---|
589 | |
---|
590 | return (vmcb->cs.attr.fields.db ? 4 : 2); |
---|
591 | } |
---|
592 | |
---|
593 | void svm_update_host_cr3(struct vcpu *v) |
---|
594 | { |
---|
595 | /* SVM doesn't have a HOST_CR3 equivalent to update. */ |
---|
596 | } |
---|
597 | |
---|
598 | void svm_update_guest_cr3(struct vcpu *v) |
---|
599 | { |
---|
600 | v->arch.hvm_svm.vmcb->cr3 = v->arch.hvm_vcpu.hw_cr3; |
---|
601 | } |
---|
602 | |
---|
603 | static void svm_update_vtpr(struct vcpu *v, unsigned long value) |
---|
604 | { |
---|
605 | struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; |
---|
606 | |
---|
607 | vmcb->vintr.fields.tpr = value & 0x0f; |
---|
608 | } |
---|
609 | |
---|
610 | unsigned long svm_get_ctrl_reg(struct vcpu *v, unsigned int num) |
---|
611 | { |
---|
612 | switch ( num ) |
---|
613 | { |
---|
614 | case 0: |
---|
615 | return v->arch.hvm_svm.cpu_shadow_cr0; |
---|
616 | case 2: |
---|
617 | return v->arch.hvm_svm.cpu_cr2; |
---|
618 | case 3: |
---|
619 | return v->arch.hvm_svm.cpu_cr3; |
---|
620 | case 4: |
---|
621 | return v->arch.hvm_svm.cpu_shadow_cr4; |
---|
622 | default: |
---|
623 | BUG(); |
---|
624 | } |
---|
625 | return 0; /* dummy */ |
---|
626 | } |
---|
627 | |
---|
628 | static unsigned long svm_get_segment_base(struct vcpu *v, enum x86_segment seg) |
---|
629 | { |
---|
630 | struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; |
---|
631 | int long_mode = 0; |
---|
632 | |
---|
633 | #ifdef __x86_64__ |
---|
634 | long_mode = vmcb->cs.attr.fields.l && svm_long_mode_enabled(v); |
---|
635 | #endif |
---|
636 | switch ( seg ) |
---|
637 | { |
---|
638 | case x86_seg_cs: return long_mode ? 0 : vmcb->cs.base; |
---|
639 | case x86_seg_ds: return long_mode ? 0 : vmcb->ds.base; |
---|
640 | case x86_seg_es: return long_mode ? 0 : vmcb->es.base; |
---|
641 | case x86_seg_fs: return vmcb->fs.base; |
---|
642 | case x86_seg_gs: return vmcb->gs.base; |
---|
643 | case x86_seg_ss: return long_mode ? 0 : vmcb->ss.base; |
---|
644 | case x86_seg_tr: return vmcb->tr.base; |
---|
645 | case x86_seg_gdtr: return vmcb->gdtr.base; |
---|
646 | case x86_seg_idtr: return vmcb->idtr.base; |
---|
647 | case x86_seg_ldtr: return vmcb->ldtr.base; |
---|
648 | } |
---|
649 | BUG(); |
---|
650 | return 0; |
---|
651 | } |
---|
652 | |
---|
653 | static void svm_get_segment_register(struct vcpu *v, enum x86_segment seg, |
---|
654 | struct segment_register *reg) |
---|
655 | { |
---|
656 | struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; |
---|
657 | switch ( seg ) |
---|
658 | { |
---|
659 | case x86_seg_cs: memcpy(reg, &vmcb->cs, sizeof(*reg)); break; |
---|
660 | case x86_seg_ds: memcpy(reg, &vmcb->ds, sizeof(*reg)); break; |
---|
661 | case x86_seg_es: memcpy(reg, &vmcb->es, sizeof(*reg)); break; |
---|
662 | case x86_seg_fs: memcpy(reg, &vmcb->fs, sizeof(*reg)); break; |
---|
663 | case x86_seg_gs: memcpy(reg, &vmcb->gs, sizeof(*reg)); break; |
---|
664 | case x86_seg_ss: memcpy(reg, &vmcb->ss, sizeof(*reg)); break; |
---|
665 | case x86_seg_tr: memcpy(reg, &vmcb->tr, sizeof(*reg)); break; |
---|
666 | case x86_seg_gdtr: memcpy(reg, &vmcb->gdtr, sizeof(*reg)); break; |
---|
667 | case x86_seg_idtr: memcpy(reg, &vmcb->idtr, sizeof(*reg)); break; |
---|
668 | case x86_seg_ldtr: memcpy(reg, &vmcb->ldtr, sizeof(*reg)); break; |
---|
669 | default: BUG(); |
---|
670 | } |
---|
671 | } |
---|
672 | |
---|
673 | /* Make sure that xen intercepts any FP accesses from current */ |
---|
674 | static void svm_stts(struct vcpu *v) |
---|
675 | { |
---|
676 | struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; |
---|
677 | |
---|
678 | /* |
---|
679 | * If the guest does not have TS enabled then we must cause and handle an |
---|
680 | * exception on first use of the FPU. If the guest *does* have TS enabled |
---|
681 | * then this is not necessary: no FPU activity can occur until the guest |
---|
682 | * clears CR0.TS, and we will initialise the FPU when that happens. |
---|
683 | */ |
---|
684 | if ( !(v->arch.hvm_svm.cpu_shadow_cr0 & X86_CR0_TS) ) |
---|
685 | { |
---|
686 | v->arch.hvm_svm.vmcb->exception_intercepts |= 1U << TRAP_no_device; |
---|
687 | vmcb->cr0 |= X86_CR0_TS; |
---|
688 | } |
---|
689 | } |
---|
690 | |
---|
691 | |
---|
692 | static void svm_set_tsc_offset(struct vcpu *v, u64 offset) |
---|
693 | { |
---|
694 | v->arch.hvm_svm.vmcb->tsc_offset = offset; |
---|
695 | } |
---|
696 | |
---|
697 | |
---|
698 | static void svm_init_ap_context( |
---|
699 | struct vcpu_guest_context *ctxt, int vcpuid, int trampoline_vector) |
---|
700 | { |
---|
701 | struct vcpu *v; |
---|
702 | struct vmcb_struct *vmcb; |
---|
703 | cpu_user_regs_t *regs; |
---|
704 | u16 cs_sel; |
---|
705 | |
---|
706 | /* We know this is safe because hvm_bringup_ap() does it */ |
---|
707 | v = current->domain->vcpu[vcpuid]; |
---|
708 | vmcb = v->arch.hvm_svm.vmcb; |
---|
709 | regs = &v->arch.guest_context.user_regs; |
---|
710 | |
---|
711 | memset(ctxt, 0, sizeof(*ctxt)); |
---|
712 | |
---|
713 | /* |
---|
714 | * We execute the trampoline code in real mode. The trampoline vector |
---|
715 | * passed to us is page alligned and is the physical frame number for |
---|
716 | * the code. We will execute this code in real mode. |
---|
717 | */ |
---|
718 | cs_sel = trampoline_vector << 8; |
---|
719 | ctxt->user_regs.eip = 0x0; |
---|
720 | ctxt->user_regs.cs = cs_sel; |
---|
721 | |
---|
722 | /* |
---|
723 | * This is the launch of an AP; set state so that we begin executing |
---|
724 | * the trampoline code in real-mode. |
---|
725 | */ |
---|
726 | svm_reset_to_realmode(v, regs); |
---|
727 | /* Adjust the vmcb's hidden register state. */ |
---|
728 | vmcb->rip = 0; |
---|
729 | vmcb->cs.sel = cs_sel; |
---|
730 | vmcb->cs.base = (cs_sel << 4); |
---|
731 | } |
---|
732 | |
---|
733 | static void svm_init_hypercall_page(struct domain *d, void *hypercall_page) |
---|
734 | { |
---|
735 | char *p; |
---|
736 | int i; |
---|
737 | |
---|
738 | memset(hypercall_page, 0, PAGE_SIZE); |
---|
739 | |
---|
740 | for ( i = 0; i < (PAGE_SIZE / 32); i++ ) |
---|
741 | { |
---|
742 | p = (char *)(hypercall_page + (i * 32)); |
---|
743 | *(u8 *)(p + 0) = 0xb8; /* mov imm32, %eax */ |
---|
744 | *(u32 *)(p + 1) = i; |
---|
745 | *(u8 *)(p + 5) = 0x0f; /* vmmcall */ |
---|
746 | *(u8 *)(p + 6) = 0x01; |
---|
747 | *(u8 *)(p + 7) = 0xd9; |
---|
748 | *(u8 *)(p + 8) = 0xc3; /* ret */ |
---|
749 | } |
---|
750 | |
---|
751 | /* Don't support HYPERVISOR_iret at the moment */ |
---|
752 | *(u16 *)(hypercall_page + (__HYPERVISOR_iret * 32)) = 0x0b0f; /* ud2 */ |
---|
753 | } |
---|
754 | |
---|
755 | static void save_svm_cpu_user_regs(struct vcpu *v, struct cpu_user_regs *ctxt) |
---|
756 | { |
---|
757 | struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; |
---|
758 | |
---|
759 | ctxt->eax = vmcb->rax; |
---|
760 | ctxt->ss = vmcb->ss.sel; |
---|
761 | ctxt->esp = vmcb->rsp; |
---|
762 | ctxt->eflags = vmcb->rflags; |
---|
763 | ctxt->cs = vmcb->cs.sel; |
---|
764 | ctxt->eip = vmcb->rip; |
---|
765 | |
---|
766 | ctxt->gs = vmcb->gs.sel; |
---|
767 | ctxt->fs = vmcb->fs.sel; |
---|
768 | ctxt->es = vmcb->es.sel; |
---|
769 | ctxt->ds = vmcb->ds.sel; |
---|
770 | } |
---|
771 | |
---|
772 | static void svm_load_cpu_guest_regs(struct vcpu *v, struct cpu_user_regs *regs) |
---|
773 | { |
---|
774 | struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; |
---|
775 | |
---|
776 | vmcb->rax = regs->eax; |
---|
777 | vmcb->ss.sel = regs->ss; |
---|
778 | vmcb->rsp = regs->esp; |
---|
779 | vmcb->rflags = regs->eflags | 2UL; |
---|
780 | vmcb->cs.sel = regs->cs; |
---|
781 | vmcb->rip = regs->eip; |
---|
782 | } |
---|
783 | |
---|
784 | static void svm_ctxt_switch_from(struct vcpu *v) |
---|
785 | { |
---|
786 | svm_save_dr(v); |
---|
787 | } |
---|
788 | |
---|
789 | static void svm_ctxt_switch_to(struct vcpu *v) |
---|
790 | { |
---|
791 | #ifdef __x86_64__ |
---|
792 | /* |
---|
793 | * This is required, because VMRUN does consistency check |
---|
794 | * and some of the DOM0 selectors are pointing to |
---|
795 | * invalid GDT locations, and cause AMD processors |
---|
796 | * to shutdown. |
---|
797 | */ |
---|
798 | set_segment_register(ds, 0); |
---|
799 | set_segment_register(es, 0); |
---|
800 | set_segment_register(ss, 0); |
---|
801 | #endif |
---|
802 | svm_restore_dr(v); |
---|
803 | } |
---|
804 | |
---|
805 | static void svm_do_resume(struct vcpu *v) |
---|
806 | { |
---|
807 | bool_t debug_state = v->domain->debugger_attached; |
---|
808 | |
---|
809 | if ( unlikely(v->arch.hvm_vcpu.debug_state_latch != debug_state) ) |
---|
810 | { |
---|
811 | uint32_t mask = (1U << TRAP_debug) | (1U << TRAP_int3); |
---|
812 | v->arch.hvm_vcpu.debug_state_latch = debug_state; |
---|
813 | if ( debug_state ) |
---|
814 | v->arch.hvm_svm.vmcb->exception_intercepts |= mask; |
---|
815 | else |
---|
816 | v->arch.hvm_svm.vmcb->exception_intercepts &= ~mask; |
---|
817 | } |
---|
818 | |
---|
819 | if ( v->arch.hvm_svm.launch_core != smp_processor_id() ) |
---|
820 | { |
---|
821 | v->arch.hvm_svm.launch_core = smp_processor_id(); |
---|
822 | hvm_migrate_timers(v); |
---|
823 | } |
---|
824 | |
---|
825 | hvm_do_resume(v); |
---|
826 | reset_stack_and_jump(svm_asm_do_resume); |
---|
827 | } |
---|
828 | |
---|
829 | static int svm_vcpu_initialise(struct vcpu *v) |
---|
830 | { |
---|
831 | int rc; |
---|
832 | |
---|
833 | v->arch.schedule_tail = svm_do_resume; |
---|
834 | v->arch.ctxt_switch_from = svm_ctxt_switch_from; |
---|
835 | v->arch.ctxt_switch_to = svm_ctxt_switch_to; |
---|
836 | |
---|
837 | v->arch.hvm_svm.launch_core = -1; |
---|
838 | |
---|
839 | if ( (rc = svm_create_vmcb(v)) != 0 ) |
---|
840 | { |
---|
841 | dprintk(XENLOG_WARNING, |
---|
842 | "Failed to create VMCB for vcpu %d: err=%d.\n", |
---|
843 | v->vcpu_id, rc); |
---|
844 | return rc; |
---|
845 | } |
---|
846 | |
---|
847 | return 0; |
---|
848 | } |
---|
849 | |
---|
850 | static void svm_vcpu_destroy(struct vcpu *v) |
---|
851 | { |
---|
852 | svm_destroy_vmcb(v); |
---|
853 | } |
---|
854 | |
---|
855 | static void svm_hvm_inject_exception( |
---|
856 | unsigned int trapnr, int errcode, unsigned long cr2) |
---|
857 | { |
---|
858 | struct vcpu *v = current; |
---|
859 | if ( trapnr == TRAP_page_fault ) |
---|
860 | v->arch.hvm_svm.vmcb->cr2 = v->arch.hvm_svm.cpu_cr2 = cr2; |
---|
861 | svm_inject_exception(v, trapnr, (errcode != -1), errcode); |
---|
862 | } |
---|
863 | |
---|
864 | static int svm_event_injection_faulted(struct vcpu *v) |
---|
865 | { |
---|
866 | struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; |
---|
867 | return vmcb->exitintinfo.fields.v; |
---|
868 | } |
---|
869 | |
---|
870 | static struct hvm_function_table svm_function_table = { |
---|
871 | .name = "SVM", |
---|
872 | .disable = stop_svm, |
---|
873 | .vcpu_initialise = svm_vcpu_initialise, |
---|
874 | .vcpu_destroy = svm_vcpu_destroy, |
---|
875 | .store_cpu_guest_regs = svm_store_cpu_guest_regs, |
---|
876 | .load_cpu_guest_regs = svm_load_cpu_guest_regs, |
---|
877 | .save_cpu_ctxt = svm_save_vmcb_ctxt, |
---|
878 | .load_cpu_ctxt = svm_load_vmcb_ctxt, |
---|
879 | .paging_enabled = svm_paging_enabled, |
---|
880 | .long_mode_enabled = svm_long_mode_enabled, |
---|
881 | .pae_enabled = svm_pae_enabled, |
---|
882 | .interrupts_enabled = svm_interrupts_enabled, |
---|
883 | .guest_x86_mode = svm_guest_x86_mode, |
---|
884 | .get_guest_ctrl_reg = svm_get_ctrl_reg, |
---|
885 | .get_segment_base = svm_get_segment_base, |
---|
886 | .get_segment_register = svm_get_segment_register, |
---|
887 | .update_host_cr3 = svm_update_host_cr3, |
---|
888 | .update_guest_cr3 = svm_update_guest_cr3, |
---|
889 | .update_vtpr = svm_update_vtpr, |
---|
890 | .stts = svm_stts, |
---|
891 | .set_tsc_offset = svm_set_tsc_offset, |
---|
892 | .inject_exception = svm_hvm_inject_exception, |
---|
893 | .init_ap_context = svm_init_ap_context, |
---|
894 | .init_hypercall_page = svm_init_hypercall_page, |
---|
895 | .event_injection_faulted = svm_event_injection_faulted |
---|
896 | }; |
---|
897 | |
---|
898 | void svm_npt_detect(void) |
---|
899 | { |
---|
900 | u32 eax, ebx, ecx, edx; |
---|
901 | |
---|
902 | /* Check CPUID for nested paging support. */ |
---|
903 | cpuid(0x8000000A, &eax, &ebx, &ecx, &edx); |
---|
904 | |
---|
905 | if ( !(edx & 1) && opt_hap_enabled ) |
---|
906 | { |
---|
907 | printk("SVM: Nested paging is not supported by this CPU.\n"); |
---|
908 | opt_hap_enabled = 0; |
---|
909 | } |
---|
910 | } |
---|
911 | |
---|
912 | int start_svm(void) |
---|
913 | { |
---|
914 | u32 eax, ecx, edx; |
---|
915 | u32 phys_hsa_lo, phys_hsa_hi; |
---|
916 | u64 phys_hsa; |
---|
917 | int cpu = smp_processor_id(); |
---|
918 | |
---|
919 | /* Xen does not fill x86_capability words except 0. */ |
---|
920 | ecx = cpuid_ecx(0x80000001); |
---|
921 | boot_cpu_data.x86_capability[5] = ecx; |
---|
922 | |
---|
923 | if ( !(test_bit(X86_FEATURE_SVME, &boot_cpu_data.x86_capability)) ) |
---|
924 | return 0; |
---|
925 | |
---|
926 | /* check whether SVM feature is disabled in BIOS */ |
---|
927 | rdmsr(MSR_K8_VM_CR, eax, edx); |
---|
928 | if ( eax & K8_VMCR_SVME_DISABLE ) |
---|
929 | { |
---|
930 | printk("AMD SVM Extension is disabled in BIOS.\n"); |
---|
931 | return 0; |
---|
932 | } |
---|
933 | |
---|
934 | if ( ((hsa[cpu] = alloc_host_save_area()) == NULL) || |
---|
935 | ((root_vmcb[cpu] = alloc_vmcb()) == NULL) ) |
---|
936 | return 0; |
---|
937 | |
---|
938 | rdmsr(MSR_EFER, eax, edx); |
---|
939 | eax |= EFER_SVME; |
---|
940 | wrmsr(MSR_EFER, eax, edx); |
---|
941 | |
---|
942 | svm_npt_detect(); |
---|
943 | |
---|
944 | /* Initialize the HSA for this core */ |
---|
945 | phys_hsa = (u64) virt_to_maddr(hsa[cpu]); |
---|
946 | phys_hsa_lo = (u32) phys_hsa; |
---|
947 | phys_hsa_hi = (u32) (phys_hsa >> 32); |
---|
948 | wrmsr(MSR_K8_VM_HSAVE_PA, phys_hsa_lo, phys_hsa_hi); |
---|
949 | |
---|
950 | root_vmcb_pa[cpu] = virt_to_maddr(root_vmcb[cpu]); |
---|
951 | |
---|
952 | if ( cpu != 0 ) |
---|
953 | return 1; |
---|
954 | |
---|
955 | setup_vmcb_dump(); |
---|
956 | |
---|
957 | hvm_enable(&svm_function_table); |
---|
958 | |
---|
959 | return 1; |
---|
960 | } |
---|
961 | |
---|
962 | static int svm_do_nested_pgfault(paddr_t gpa, struct cpu_user_regs *regs) |
---|
963 | { |
---|
964 | if (mmio_space(gpa)) { |
---|
965 | handle_mmio(gpa); |
---|
966 | return 1; |
---|
967 | } |
---|
968 | |
---|
969 | /* We should not reach here. Otherwise, P2M table is not correct.*/ |
---|
970 | return 0; |
---|
971 | } |
---|
972 | |
---|
973 | static void svm_do_no_device_fault(struct vmcb_struct *vmcb) |
---|
974 | { |
---|
975 | struct vcpu *v = current; |
---|
976 | |
---|
977 | setup_fpu(v); |
---|
978 | vmcb->exception_intercepts &= ~(1U << TRAP_no_device); |
---|
979 | |
---|
980 | if ( !(v->arch.hvm_svm.cpu_shadow_cr0 & X86_CR0_TS) ) |
---|
981 | vmcb->cr0 &= ~X86_CR0_TS; |
---|
982 | } |
---|
983 | |
---|
984 | /* Reserved bits ECX: [31:14], [12:4], [2:1]*/ |
---|
985 | #define SVM_VCPU_CPUID_L1_ECX_RESERVED 0xffffdff6 |
---|
986 | /* Reserved bits EDX: [31:29], [27], [22:20], [18], [10] */ |
---|
987 | #define SVM_VCPU_CPUID_L1_EDX_RESERVED 0xe8740400 |
---|
988 | |
---|
989 | static void svm_vmexit_do_cpuid(struct vmcb_struct *vmcb, |
---|
990 | struct cpu_user_regs *regs) |
---|
991 | { |
---|
992 | unsigned long input = regs->eax; |
---|
993 | unsigned int eax, ebx, ecx, edx; |
---|
994 | struct vcpu *v = current; |
---|
995 | int inst_len; |
---|
996 | |
---|
997 | hvm_cpuid(input, &eax, &ebx, &ecx, &edx); |
---|
998 | |
---|
999 | if ( input == 0x00000001 ) |
---|
1000 | { |
---|
1001 | /* Clear out reserved bits. */ |
---|
1002 | ecx &= ~SVM_VCPU_CPUID_L1_ECX_RESERVED; |
---|
1003 | edx &= ~SVM_VCPU_CPUID_L1_EDX_RESERVED; |
---|
1004 | |
---|
1005 | /* Guest should only see one logical processor. |
---|
1006 | * See details on page 23 of AMD CPUID Specification. |
---|
1007 | */ |
---|
1008 | clear_bit(X86_FEATURE_HT & 31, &edx); /* clear the hyperthread bit */ |
---|
1009 | ebx &= 0xFF00FFFF; /* clear the logical processor count when HTT=0 */ |
---|
1010 | ebx |= 0x00010000; /* set to 1 just for precaution */ |
---|
1011 | } |
---|
1012 | else if ( input == 0x80000001 ) |
---|
1013 | { |
---|
1014 | if ( vlapic_hw_disabled(vcpu_vlapic(v)) ) |
---|
1015 | clear_bit(X86_FEATURE_APIC & 31, &edx); |
---|
1016 | |
---|
1017 | #if CONFIG_PAGING_LEVELS >= 3 |
---|
1018 | if ( !v->domain->arch.hvm_domain.params[HVM_PARAM_PAE_ENABLED] ) |
---|
1019 | #endif |
---|
1020 | clear_bit(X86_FEATURE_PAE & 31, &edx); |
---|
1021 | |
---|
1022 | clear_bit(X86_FEATURE_PSE36 & 31, &edx); |
---|
1023 | |
---|
1024 | /* Clear the Cmp_Legacy bit |
---|
1025 | * This bit is supposed to be zero when HTT = 0. |
---|
1026 | * See details on page 23 of AMD CPUID Specification. |
---|
1027 | */ |
---|
1028 | clear_bit(X86_FEATURE_CMP_LEGACY & 31, &ecx); |
---|
1029 | |
---|
1030 | /* Make SVM feature invisible to the guest. */ |
---|
1031 | clear_bit(X86_FEATURE_SVME & 31, &ecx); |
---|
1032 | |
---|
1033 | /* So far, we do not support 3DNow for the guest. */ |
---|
1034 | clear_bit(X86_FEATURE_3DNOW & 31, &edx); |
---|
1035 | clear_bit(X86_FEATURE_3DNOWEXT & 31, &edx); |
---|
1036 | /* no FFXSR instructions feature. */ |
---|
1037 | clear_bit(X86_FEATURE_FFXSR & 31, &edx); |
---|
1038 | } |
---|
1039 | else if ( input == 0x80000007 || input == 0x8000000A ) |
---|
1040 | { |
---|
1041 | /* Mask out features of power management and SVM extension. */ |
---|
1042 | eax = ebx = ecx = edx = 0; |
---|
1043 | } |
---|
1044 | else if ( input == 0x80000008 ) |
---|
1045 | { |
---|
1046 | /* Make sure Number of CPU core is 1 when HTT=0 */ |
---|
1047 | ecx &= 0xFFFFFF00; |
---|
1048 | } |
---|
1049 | |
---|
1050 | regs->eax = (unsigned long)eax; |
---|
1051 | regs->ebx = (unsigned long)ebx; |
---|
1052 | regs->ecx = (unsigned long)ecx; |
---|
1053 | regs->edx = (unsigned long)edx; |
---|
1054 | |
---|
1055 | HVMTRACE_3D(CPUID, v, input, |
---|
1056 | ((uint64_t)eax << 32) | ebx, ((uint64_t)ecx << 32) | edx); |
---|
1057 | |
---|
1058 | inst_len = __get_instruction_length(v, INSTR_CPUID, NULL); |
---|
1059 | ASSERT(inst_len > 0); |
---|
1060 | __update_guest_eip(vmcb, inst_len); |
---|
1061 | } |
---|
1062 | |
---|
1063 | static inline unsigned long *get_reg_p( |
---|
1064 | unsigned int gpreg, |
---|
1065 | struct cpu_user_regs *regs, struct vmcb_struct *vmcb) |
---|
1066 | { |
---|
1067 | unsigned long *reg_p = NULL; |
---|
1068 | switch (gpreg) |
---|
1069 | { |
---|
1070 | case SVM_REG_EAX: |
---|
1071 | reg_p = (unsigned long *)®s->eax; |
---|
1072 | break; |
---|
1073 | case SVM_REG_EBX: |
---|
1074 | reg_p = (unsigned long *)®s->ebx; |
---|
1075 | break; |
---|
1076 | case SVM_REG_ECX: |
---|
1077 | reg_p = (unsigned long *)®s->ecx; |
---|
1078 | break; |
---|
1079 | case SVM_REG_EDX: |
---|
1080 | reg_p = (unsigned long *)®s->edx; |
---|
1081 | break; |
---|
1082 | case SVM_REG_EDI: |
---|
1083 | reg_p = (unsigned long *)®s->edi; |
---|
1084 | break; |
---|
1085 | case SVM_REG_ESI: |
---|
1086 | reg_p = (unsigned long *)®s->esi; |
---|
1087 | break; |
---|
1088 | case SVM_REG_EBP: |
---|
1089 | reg_p = (unsigned long *)®s->ebp; |
---|
1090 | break; |
---|
1091 | case SVM_REG_ESP: |
---|
1092 | reg_p = (unsigned long *)&vmcb->rsp; |
---|
1093 | break; |
---|
1094 | #ifdef __x86_64__ |
---|
1095 | case SVM_REG_R8: |
---|
1096 | reg_p = (unsigned long *)®s->r8; |
---|
1097 | break; |
---|
1098 | case SVM_REG_R9: |
---|
1099 | reg_p = (unsigned long *)®s->r9; |
---|
1100 | break; |
---|
1101 | case SVM_REG_R10: |
---|
1102 | reg_p = (unsigned long *)®s->r10; |
---|
1103 | break; |
---|
1104 | case SVM_REG_R11: |
---|
1105 | reg_p = (unsigned long *)®s->r11; |
---|
1106 | break; |
---|
1107 | case SVM_REG_R12: |
---|
1108 | reg_p = (unsigned long *)®s->r12; |
---|
1109 | break; |
---|
1110 | case SVM_REG_R13: |
---|
1111 | reg_p = (unsigned long *)®s->r13; |
---|
1112 | break; |
---|
1113 | case SVM_REG_R14: |
---|
1114 | reg_p = (unsigned long *)®s->r14; |
---|
1115 | break; |
---|
1116 | case SVM_REG_R15: |
---|
1117 | reg_p = (unsigned long *)®s->r15; |
---|
1118 | break; |
---|
1119 | #endif |
---|
1120 | default: |
---|
1121 | BUG(); |
---|
1122 | } |
---|
1123 | |
---|
1124 | return reg_p; |
---|
1125 | } |
---|
1126 | |
---|
1127 | |
---|
1128 | static inline unsigned long get_reg( |
---|
1129 | unsigned int gpreg, struct cpu_user_regs *regs, struct vmcb_struct *vmcb) |
---|
1130 | { |
---|
1131 | unsigned long *gp; |
---|
1132 | gp = get_reg_p(gpreg, regs, vmcb); |
---|
1133 | return *gp; |
---|
1134 | } |
---|
1135 | |
---|
1136 | |
---|
1137 | static inline void set_reg( |
---|
1138 | unsigned int gpreg, unsigned long value, |
---|
1139 | struct cpu_user_regs *regs, struct vmcb_struct *vmcb) |
---|
1140 | { |
---|
1141 | unsigned long *gp; |
---|
1142 | gp = get_reg_p(gpreg, regs, vmcb); |
---|
1143 | *gp = value; |
---|
1144 | } |
---|
1145 | |
---|
1146 | |
---|
1147 | static void svm_dr_access(struct vcpu *v, struct cpu_user_regs *regs) |
---|
1148 | { |
---|
1149 | struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; |
---|
1150 | |
---|
1151 | HVMTRACE_0D(DR_WRITE, v); |
---|
1152 | |
---|
1153 | v->arch.hvm_vcpu.flag_dr_dirty = 1; |
---|
1154 | |
---|
1155 | __restore_debug_registers(v); |
---|
1156 | |
---|
1157 | /* allow the guest full access to the debug registers */ |
---|
1158 | vmcb->dr_intercepts = 0; |
---|
1159 | } |
---|
1160 | |
---|
1161 | |
---|
1162 | static void svm_get_prefix_info(struct vcpu *v, unsigned int dir, |
---|
1163 | svm_segment_register_t **seg, |
---|
1164 | unsigned int *asize) |
---|
1165 | { |
---|
1166 | struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; |
---|
1167 | unsigned char inst[MAX_INST_LEN]; |
---|
1168 | int i; |
---|
1169 | |
---|
1170 | memset(inst, 0, MAX_INST_LEN); |
---|
1171 | if (inst_copy_from_guest(inst, svm_rip2pointer(v), sizeof(inst)) |
---|
1172 | != MAX_INST_LEN) |
---|
1173 | { |
---|
1174 | gdprintk(XENLOG_ERR, "get guest instruction failed\n"); |
---|
1175 | domain_crash(current->domain); |
---|
1176 | return; |
---|
1177 | } |
---|
1178 | |
---|
1179 | for (i = 0; i < MAX_INST_LEN; i++) |
---|
1180 | { |
---|
1181 | switch (inst[i]) |
---|
1182 | { |
---|
1183 | case 0xf3: /* REPZ */ |
---|
1184 | case 0xf2: /* REPNZ */ |
---|
1185 | case 0xf0: /* LOCK */ |
---|
1186 | case 0x66: /* data32 */ |
---|
1187 | #ifdef __x86_64__ |
---|
1188 | /* REX prefixes */ |
---|
1189 | case 0x40: |
---|
1190 | case 0x41: |
---|
1191 | case 0x42: |
---|
1192 | case 0x43: |
---|
1193 | case 0x44: |
---|
1194 | case 0x45: |
---|
1195 | case 0x46: |
---|
1196 | case 0x47: |
---|
1197 | |
---|
1198 | case 0x48: |
---|
1199 | case 0x49: |
---|
1200 | case 0x4a: |
---|
1201 | case 0x4b: |
---|
1202 | case 0x4c: |
---|
1203 | case 0x4d: |
---|
1204 | case 0x4e: |
---|
1205 | case 0x4f: |
---|
1206 | #endif |
---|
1207 | continue; |
---|
1208 | case 0x67: /* addr32 */ |
---|
1209 | *asize ^= 48; /* Switch 16/32 bits */ |
---|
1210 | continue; |
---|
1211 | case 0x2e: /* CS */ |
---|
1212 | *seg = &vmcb->cs; |
---|
1213 | continue; |
---|
1214 | case 0x36: /* SS */ |
---|
1215 | *seg = &vmcb->ss; |
---|
1216 | continue; |
---|
1217 | case 0x26: /* ES */ |
---|
1218 | *seg = &vmcb->es; |
---|
1219 | continue; |
---|
1220 | case 0x64: /* FS */ |
---|
1221 | *seg = &vmcb->fs; |
---|
1222 | continue; |
---|
1223 | case 0x65: /* GS */ |
---|
1224 | *seg = &vmcb->gs; |
---|
1225 | continue; |
---|
1226 | case 0x3e: /* DS */ |
---|
1227 | *seg = &vmcb->ds; |
---|
1228 | continue; |
---|
1229 | default: |
---|
1230 | break; |
---|
1231 | } |
---|
1232 | return; |
---|
1233 | } |
---|
1234 | } |
---|
1235 | |
---|
1236 | |
---|
1237 | /* Get the address of INS/OUTS instruction */ |
---|
1238 | static inline int svm_get_io_address( |
---|
1239 | struct vcpu *v, struct cpu_user_regs *regs, |
---|
1240 | unsigned int size, ioio_info_t info, |
---|
1241 | unsigned long *count, unsigned long *addr) |
---|
1242 | { |
---|
1243 | unsigned long reg; |
---|
1244 | unsigned int asize, isize; |
---|
1245 | int long_mode = 0; |
---|
1246 | svm_segment_register_t *seg = NULL; |
---|
1247 | struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; |
---|
1248 | |
---|
1249 | #ifdef __x86_64__ |
---|
1250 | /* If we're in long mode, we shouldn't check the segment presence & limit */ |
---|
1251 | long_mode = vmcb->cs.attr.fields.l && svm_long_mode_enabled(v); |
---|
1252 | #endif |
---|
1253 | |
---|
1254 | /* d field of cs.attr is 1 for 32-bit, 0 for 16 or 64 bit. |
---|
1255 | * l field combined with EFER_LMA says whether it's 16 or 64 bit. |
---|
1256 | */ |
---|
1257 | asize = (long_mode)?64:((vmcb->cs.attr.fields.db)?32:16); |
---|
1258 | |
---|
1259 | |
---|
1260 | /* The ins/outs instructions are single byte, so if we have got more |
---|
1261 | * than one byte (+ maybe rep-prefix), we have some prefix so we need |
---|
1262 | * to figure out what it is... |
---|
1263 | */ |
---|
1264 | isize = vmcb->exitinfo2 - vmcb->rip; |
---|
1265 | |
---|
1266 | if (info.fields.rep) |
---|
1267 | isize --; |
---|
1268 | |
---|
1269 | if (isize > 1) |
---|
1270 | svm_get_prefix_info(v, info.fields.type, &seg, &asize); |
---|
1271 | |
---|
1272 | if (info.fields.type == IOREQ_WRITE) |
---|
1273 | { |
---|
1274 | reg = regs->esi; |
---|
1275 | if (!seg) /* If no prefix, used DS. */ |
---|
1276 | seg = &vmcb->ds; |
---|
1277 | if (!long_mode && (seg->attr.fields.type & 0xa) == 0x8) { |
---|
1278 | svm_inject_exception(v, TRAP_gp_fault, 1, 0); |
---|
1279 | return 0; |
---|
1280 | } |
---|
1281 | } |
---|
1282 | else |
---|
1283 | { |
---|
1284 | reg = regs->edi; |
---|
1285 | seg = &vmcb->es; /* Note: This is ALWAYS ES. */ |
---|
1286 | if (!long_mode && (seg->attr.fields.type & 0xa) != 0x2) { |
---|
1287 | svm_inject_exception(v, TRAP_gp_fault, 1, 0); |
---|
1288 | return 0; |
---|
1289 | } |
---|
1290 | } |
---|
1291 | |
---|
1292 | /* If the segment isn't present, give GP fault! */ |
---|
1293 | if (!long_mode && !seg->attr.fields.p) |
---|
1294 | { |
---|
1295 | svm_inject_exception(v, TRAP_gp_fault, 1, 0); |
---|
1296 | return 0; |
---|
1297 | } |
---|
1298 | |
---|
1299 | if (asize == 16) |
---|
1300 | { |
---|
1301 | *addr = (reg & 0xFFFF); |
---|
1302 | *count = regs->ecx & 0xffff; |
---|
1303 | } |
---|
1304 | else |
---|
1305 | { |
---|
1306 | *addr = reg; |
---|
1307 | *count = regs->ecx; |
---|
1308 | } |
---|
1309 | if (!info.fields.rep) |
---|
1310 | *count = 1; |
---|
1311 | |
---|
1312 | if (!long_mode) |
---|
1313 | { |
---|
1314 | ASSERT(*addr == (u32)*addr); |
---|
1315 | if ((u32)(*addr + size - 1) < (u32)*addr || |
---|
1316 | (seg->attr.fields.type & 0xc) != 0x4 ? |
---|
1317 | *addr + size - 1 > seg->limit : |
---|
1318 | *addr <= seg->limit) |
---|
1319 | { |
---|
1320 | svm_inject_exception(v, TRAP_gp_fault, 1, 0); |
---|
1321 | return 0; |
---|
1322 | } |
---|
1323 | |
---|
1324 | /* Check the limit for repeated instructions, as above we checked only |
---|
1325 | the first instance. Truncate the count if a limit violation would |
---|
1326 | occur. Note that the checking is not necessary for page granular |
---|
1327 | segments as transfers crossing page boundaries will be broken up |
---|
1328 | anyway. */ |
---|
1329 | if (!seg->attr.fields.g && *count > 1) |
---|
1330 | { |
---|
1331 | if ((seg->attr.fields.type & 0xc) != 0x4) |
---|
1332 | { |
---|
1333 | /* expand-up */ |
---|
1334 | if (!(regs->eflags & EF_DF)) |
---|
1335 | { |
---|
1336 | if (*addr + *count * size - 1 < *addr || |
---|
1337 | *addr + *count * size - 1 > seg->limit) |
---|
1338 | *count = (seg->limit + 1UL - *addr) / size; |
---|
1339 | } |
---|
1340 | else |
---|
1341 | { |
---|
1342 | if (*count - 1 > *addr / size) |
---|
1343 | *count = *addr / size + 1; |
---|
1344 | } |
---|
1345 | } |
---|
1346 | else |
---|
1347 | { |
---|
1348 | /* expand-down */ |
---|
1349 | if (!(regs->eflags & EF_DF)) |
---|
1350 | { |
---|
1351 | if (*count - 1 > -(s32)*addr / size) |
---|
1352 | *count = -(s32)*addr / size + 1UL; |
---|
1353 | } |
---|
1354 | else |
---|
1355 | { |
---|
1356 | if (*addr < (*count - 1) * size || |
---|
1357 | *addr - (*count - 1) * size <= seg->limit) |
---|
1358 | *count = (*addr - seg->limit - 1) / size + 1; |
---|
1359 | } |
---|
1360 | } |
---|
1361 | ASSERT(*count); |
---|
1362 | } |
---|
1363 | |
---|
1364 | *addr += seg->base; |
---|
1365 | } |
---|
1366 | #ifdef __x86_64__ |
---|
1367 | else |
---|
1368 | { |
---|
1369 | if (seg == &vmcb->fs || seg == &vmcb->gs) |
---|
1370 | *addr += seg->base; |
---|
1371 | |
---|
1372 | if (!is_canonical_address(*addr) || |
---|
1373 | !is_canonical_address(*addr + size - 1)) |
---|
1374 | { |
---|
1375 | svm_inject_exception(v, TRAP_gp_fault, 1, 0); |
---|
1376 | return 0; |
---|
1377 | } |
---|
1378 | if (*count > (1UL << 48) / size) |
---|
1379 | *count = (1UL << 48) / size; |
---|
1380 | if (!(regs->eflags & EF_DF)) |
---|
1381 | { |
---|
1382 | if (*addr + *count * size - 1 < *addr || |
---|
1383 | !is_canonical_address(*addr + *count * size - 1)) |
---|
1384 | *count = (*addr & ~((1UL << 48) - 1)) / size; |
---|
1385 | } |
---|
1386 | else |
---|
1387 | { |
---|
1388 | if ((*count - 1) * size > *addr || |
---|
1389 | !is_canonical_address(*addr + (*count - 1) * size)) |
---|
1390 | *count = (*addr & ~((1UL << 48) - 1)) / size + 1; |
---|
1391 | } |
---|
1392 | ASSERT(*count); |
---|
1393 | } |
---|
1394 | #endif |
---|
1395 | |
---|
1396 | return 1; |
---|
1397 | } |
---|
1398 | |
---|
1399 | |
---|
1400 | static void svm_io_instruction(struct vcpu *v) |
---|
1401 | { |
---|
1402 | struct cpu_user_regs *regs; |
---|
1403 | struct hvm_io_op *pio_opp; |
---|
1404 | unsigned int port; |
---|
1405 | unsigned int size, dir, df; |
---|
1406 | ioio_info_t info; |
---|
1407 | struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; |
---|
1408 | |
---|
1409 | pio_opp = ¤t->arch.hvm_vcpu.io_op; |
---|
1410 | pio_opp->instr = INSTR_PIO; |
---|
1411 | pio_opp->flags = 0; |
---|
1412 | |
---|
1413 | regs = &pio_opp->io_context; |
---|
1414 | |
---|
1415 | /* Copy current guest state into io instruction state structure. */ |
---|
1416 | memcpy(regs, guest_cpu_user_regs(), HVM_CONTEXT_STACK_BYTES); |
---|
1417 | hvm_store_cpu_guest_regs(v, regs, NULL); |
---|
1418 | |
---|
1419 | info.bytes = vmcb->exitinfo1; |
---|
1420 | |
---|
1421 | port = info.fields.port; /* port used to be addr */ |
---|
1422 | dir = info.fields.type; /* direction */ |
---|
1423 | df = regs->eflags & X86_EFLAGS_DF ? 1 : 0; |
---|
1424 | |
---|
1425 | if (info.fields.sz32) |
---|
1426 | size = 4; |
---|
1427 | else if (info.fields.sz16) |
---|
1428 | size = 2; |
---|
1429 | else |
---|
1430 | size = 1; |
---|
1431 | |
---|
1432 | if (dir==IOREQ_READ) |
---|
1433 | HVMTRACE_2D(IO_READ, v, port, size); |
---|
1434 | else |
---|
1435 | HVMTRACE_2D(IO_WRITE, v, port, size); |
---|
1436 | |
---|
1437 | HVM_DBG_LOG(DBG_LEVEL_IO, |
---|
1438 | "svm_io_instruction: port 0x%x eip=%x:%"PRIx64", " |
---|
1439 | "exit_qualification = %"PRIx64, |
---|
1440 | port, vmcb->cs.sel, vmcb->rip, info.bytes); |
---|
1441 | |
---|
1442 | /* string instruction */ |
---|
1443 | if (info.fields.str) |
---|
1444 | { |
---|
1445 | unsigned long addr, count; |
---|
1446 | paddr_t paddr; |
---|
1447 | unsigned long gfn; |
---|
1448 | int sign = regs->eflags & X86_EFLAGS_DF ? -1 : 1; |
---|
1449 | |
---|
1450 | if (!svm_get_io_address(v, regs, size, info, &count, &addr)) |
---|
1451 | { |
---|
1452 | /* We failed to get a valid address, so don't do the IO operation - |
---|
1453 | * it would just get worse if we do! Hopefully the guest is handing |
---|
1454 | * gp-faults... |
---|
1455 | */ |
---|
1456 | return; |
---|
1457 | } |
---|
1458 | |
---|
1459 | /* "rep" prefix */ |
---|
1460 | if (info.fields.rep) |
---|
1461 | { |
---|
1462 | pio_opp->flags |= REPZ; |
---|
1463 | } |
---|
1464 | |
---|
1465 | /* Translate the address to a physical address */ |
---|
1466 | gfn = paging_gva_to_gfn(v, addr); |
---|
1467 | if ( gfn == INVALID_GFN ) |
---|
1468 | { |
---|
1469 | /* The guest does not have the RAM address mapped. |
---|
1470 | * Need to send in a page fault */ |
---|
1471 | int errcode = 0; |
---|
1472 | /* IO read --> memory write */ |
---|
1473 | if ( dir == IOREQ_READ ) errcode |= PFEC_write_access; |
---|
1474 | svm_hvm_inject_exception(TRAP_page_fault, errcode, addr); |
---|
1475 | return; |
---|
1476 | } |
---|
1477 | paddr = (paddr_t)gfn << PAGE_SHIFT | (addr & ~PAGE_MASK); |
---|
1478 | |
---|
1479 | /* |
---|
1480 | * Handle string pio instructions that cross pages or that |
---|
1481 | * are unaligned. See the comments in hvm_platform.c/handle_mmio() |
---|
1482 | */ |
---|
1483 | if ((addr & PAGE_MASK) != ((addr + size - 1) & PAGE_MASK)) |
---|
1484 | { |
---|
1485 | unsigned long value = 0; |
---|
1486 | |
---|
1487 | pio_opp->flags |= OVERLAP; |
---|
1488 | pio_opp->addr = addr; |
---|
1489 | |
---|
1490 | if (dir == IOREQ_WRITE) /* OUTS */ |
---|
1491 | { |
---|
1492 | if ( hvm_paging_enabled(current) ) |
---|
1493 | { |
---|
1494 | int rv = hvm_copy_from_guest_virt(&value, addr, size); |
---|
1495 | if ( rv != 0 ) |
---|
1496 | { |
---|
1497 | /* Failed on the page-spanning copy. Inject PF into |
---|
1498 | * the guest for the address where we failed. */ |
---|
1499 | addr += size - rv; |
---|
1500 | gdprintk(XENLOG_DEBUG, "Pagefault reading non-io side " |
---|
1501 | "of a page-spanning PIO: va=%#lx\n", addr); |
---|
1502 | svm_hvm_inject_exception(TRAP_page_fault, 0, addr); |
---|
1503 | return; |
---|
1504 | } |
---|
1505 | } |
---|
1506 | else |
---|
1507 | (void) hvm_copy_from_guest_phys(&value, addr, size); |
---|
1508 | } else /* dir != IOREQ_WRITE */ |
---|
1509 | /* Remember where to write the result, as a *VA*. |
---|
1510 | * Must be a VA so we can handle the page overlap |
---|
1511 | * correctly in hvm_pio_assist() */ |
---|
1512 | pio_opp->addr = addr; |
---|
1513 | |
---|
1514 | if (count == 1) |
---|
1515 | regs->eip = vmcb->exitinfo2; |
---|
1516 | |
---|
1517 | send_pio_req(port, 1, size, value, dir, df, 0); |
---|
1518 | } |
---|
1519 | else |
---|
1520 | { |
---|
1521 | unsigned long last_addr = sign > 0 ? addr + count * size - 1 |
---|
1522 | : addr - (count - 1) * size; |
---|
1523 | |
---|
1524 | if ((addr & PAGE_MASK) != (last_addr & PAGE_MASK)) |
---|
1525 | { |
---|
1526 | if (sign > 0) |
---|
1527 | count = (PAGE_SIZE - (addr & ~PAGE_MASK)) / size; |
---|
1528 | else |
---|
1529 | count = (addr & ~PAGE_MASK) / size + 1; |
---|
1530 | } |
---|
1531 | else |
---|
1532 | regs->eip = vmcb->exitinfo2; |
---|
1533 | |
---|
1534 | send_pio_req(port, count, size, paddr, dir, df, 1); |
---|
1535 | } |
---|
1536 | } |
---|
1537 | else |
---|
1538 | { |
---|
1539 | /* |
---|
1540 | * On SVM, the RIP of the intruction following the IN/OUT is saved in |
---|
1541 | * ExitInfo2 |
---|
1542 | */ |
---|
1543 | regs->eip = vmcb->exitinfo2; |
---|
1544 | |
---|
1545 | if (port == 0xe9 && dir == IOREQ_WRITE && size == 1) |
---|
1546 | hvm_print_line(v, regs->eax); /* guest debug output */ |
---|
1547 | |
---|
1548 | send_pio_req(port, 1, size, regs->eax, dir, df, 0); |
---|
1549 | } |
---|
1550 | } |
---|
1551 | |
---|
1552 | static int svm_set_cr0(unsigned long value) |
---|
1553 | { |
---|
1554 | struct vcpu *v = current; |
---|
1555 | unsigned long mfn, old_value = v->arch.hvm_svm.cpu_shadow_cr0; |
---|
1556 | struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; |
---|
1557 | unsigned long old_base_mfn; |
---|
1558 | |
---|
1559 | HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR0 value = %lx\n", value); |
---|
1560 | |
---|
1561 | /* ET is reserved and should be always be 1. */ |
---|
1562 | value |= X86_CR0_ET; |
---|
1563 | |
---|
1564 | if ( (value & (X86_CR0_PE|X86_CR0_PG)) == X86_CR0_PG ) |
---|
1565 | { |
---|
1566 | svm_inject_exception(v, TRAP_gp_fault, 1, 0); |
---|
1567 | return 0; |
---|
1568 | } |
---|
1569 | |
---|
1570 | /* TS cleared? Then initialise FPU now. */ |
---|
1571 | if ( !(value & X86_CR0_TS) ) |
---|
1572 | { |
---|
1573 | setup_fpu(v); |
---|
1574 | vmcb->exception_intercepts &= ~(1U << TRAP_no_device); |
---|
1575 | } |
---|
1576 | |
---|
1577 | if ( (value & X86_CR0_PG) && !(old_value & X86_CR0_PG) ) |
---|
1578 | { |
---|
1579 | #if defined(__x86_64__) |
---|
1580 | if ( svm_lme_is_set(v) ) |
---|
1581 | { |
---|
1582 | if ( !svm_cr4_pae_is_set(v) ) |
---|
1583 | { |
---|
1584 | HVM_DBG_LOG(DBG_LEVEL_1, "Enable paging before PAE enable\n"); |
---|
1585 | svm_inject_exception(v, TRAP_gp_fault, 1, 0); |
---|
1586 | return 0; |
---|
1587 | } |
---|
1588 | HVM_DBG_LOG(DBG_LEVEL_1, "Enable the Long mode\n"); |
---|
1589 | v->arch.hvm_svm.cpu_shadow_efer |= EFER_LMA; |
---|
1590 | vmcb->efer |= EFER_LMA | EFER_LME; |
---|
1591 | } |
---|
1592 | #endif /* __x86_64__ */ |
---|
1593 | |
---|
1594 | if ( !paging_mode_hap(v->domain) ) |
---|
1595 | { |
---|
1596 | /* The guest CR3 must be pointing to the guest physical. */ |
---|
1597 | mfn = get_mfn_from_gpfn(v->arch.hvm_svm.cpu_cr3 >> PAGE_SHIFT); |
---|
1598 | if ( !mfn_valid(mfn) || !get_page(mfn_to_page(mfn), v->domain)) |
---|
1599 | { |
---|
1600 | gdprintk(XENLOG_ERR, "Invalid CR3 value = %lx (mfn=%lx)\n", |
---|
1601 | v->arch.hvm_svm.cpu_cr3, mfn); |
---|
1602 | domain_crash(v->domain); |
---|
1603 | return 0; |
---|
1604 | } |
---|
1605 | |
---|
1606 | /* Now arch.guest_table points to machine physical. */ |
---|
1607 | old_base_mfn = pagetable_get_pfn(v->arch.guest_table); |
---|
1608 | v->arch.guest_table = pagetable_from_pfn(mfn); |
---|
1609 | if ( old_base_mfn ) |
---|
1610 | put_page(mfn_to_page(old_base_mfn)); |
---|
1611 | |
---|
1612 | HVM_DBG_LOG(DBG_LEVEL_VMMU, "New arch.guest_table = %lx", |
---|
1613 | (unsigned long) (mfn << PAGE_SHIFT)); |
---|
1614 | } |
---|
1615 | } |
---|
1616 | else if ( !(value & X86_CR0_PG) && (old_value & X86_CR0_PG) ) |
---|
1617 | { |
---|
1618 | /* When CR0.PG is cleared, LMA is cleared immediately. */ |
---|
1619 | if ( svm_long_mode_enabled(v) ) |
---|
1620 | { |
---|
1621 | vmcb->efer &= ~(EFER_LME | EFER_LMA); |
---|
1622 | v->arch.hvm_svm.cpu_shadow_efer &= ~EFER_LMA; |
---|
1623 | } |
---|
1624 | |
---|
1625 | if ( !paging_mode_hap(v->domain) && v->arch.hvm_svm.cpu_cr3 ) |
---|
1626 | { |
---|
1627 | put_page(mfn_to_page(get_mfn_from_gpfn( |
---|
1628 | v->arch.hvm_svm.cpu_cr3 >> PAGE_SHIFT))); |
---|
1629 | v->arch.guest_table = pagetable_null(); |
---|
1630 | } |
---|
1631 | } |
---|
1632 | |
---|
1633 | vmcb->cr0 = v->arch.hvm_svm.cpu_shadow_cr0 = value; |
---|
1634 | if ( !paging_mode_hap(v->domain) ) |
---|
1635 | vmcb->cr0 |= X86_CR0_PG | X86_CR0_WP; |
---|
1636 | |
---|
1637 | if ( (value ^ old_value) & X86_CR0_PG ) |
---|
1638 | paging_update_paging_modes(v); |
---|
1639 | |
---|
1640 | return 1; |
---|
1641 | } |
---|
1642 | |
---|
1643 | /* |
---|
1644 | * Read from control registers. CR0 and CR4 are read from the shadow. |
---|
1645 | */ |
---|
1646 | static void mov_from_cr(int cr, int gp, struct cpu_user_regs *regs) |
---|
1647 | { |
---|
1648 | unsigned long value = 0; |
---|
1649 | struct vcpu *v = current; |
---|
1650 | struct vlapic *vlapic = vcpu_vlapic(v); |
---|
1651 | struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; |
---|
1652 | |
---|
1653 | switch ( cr ) |
---|
1654 | { |
---|
1655 | case 0: |
---|
1656 | value = v->arch.hvm_svm.cpu_shadow_cr0; |
---|
1657 | break; |
---|
1658 | case 2: |
---|
1659 | value = vmcb->cr2; |
---|
1660 | break; |
---|
1661 | case 3: |
---|
1662 | value = (unsigned long)v->arch.hvm_svm.cpu_cr3; |
---|
1663 | break; |
---|
1664 | case 4: |
---|
1665 | value = (unsigned long)v->arch.hvm_svm.cpu_shadow_cr4; |
---|
1666 | break; |
---|
1667 | case 8: |
---|
1668 | value = (unsigned long)vlapic_get_reg(vlapic, APIC_TASKPRI); |
---|
1669 | value = (value & 0xF0) >> 4; |
---|
1670 | break; |
---|
1671 | |
---|
1672 | default: |
---|
1673 | domain_crash(v->domain); |
---|
1674 | return; |
---|
1675 | } |
---|
1676 | |
---|
1677 | HVMTRACE_2D(CR_READ, v, cr, value); |
---|
1678 | |
---|
1679 | set_reg(gp, value, regs, vmcb); |
---|
1680 | |
---|
1681 | HVM_DBG_LOG(DBG_LEVEL_VMMU, "mov_from_cr: CR%d, value = %lx,", cr, value); |
---|
1682 | } |
---|
1683 | |
---|
1684 | |
---|
1685 | /* |
---|
1686 | * Write to control registers |
---|
1687 | */ |
---|
1688 | static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs) |
---|
1689 | { |
---|
1690 | unsigned long value, old_cr, old_base_mfn, mfn; |
---|
1691 | struct vcpu *v = current; |
---|
1692 | struct vlapic *vlapic = vcpu_vlapic(v); |
---|
1693 | struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; |
---|
1694 | |
---|
1695 | value = get_reg(gpreg, regs, vmcb); |
---|
1696 | |
---|
1697 | HVMTRACE_2D(CR_WRITE, v, cr, value); |
---|
1698 | |
---|
1699 | HVM_DBG_LOG(DBG_LEVEL_1, "mov_to_cr: CR%d, value = %lx,", cr, value); |
---|
1700 | HVM_DBG_LOG(DBG_LEVEL_1, "current = %lx,", (unsigned long) current); |
---|
1701 | |
---|
1702 | switch ( cr ) |
---|
1703 | { |
---|
1704 | case 0: |
---|
1705 | return svm_set_cr0(value); |
---|
1706 | |
---|
1707 | case 3: |
---|
1708 | if ( paging_mode_hap(v->domain) ) |
---|
1709 | { |
---|
1710 | vmcb->cr3 = v->arch.hvm_svm.cpu_cr3 = value; |
---|
1711 | break; |
---|
1712 | } |
---|
1713 | |
---|
1714 | /* If paging is not enabled yet, simply copy the value to CR3. */ |
---|
1715 | if ( !svm_paging_enabled(v) ) |
---|
1716 | { |
---|
1717 | v->arch.hvm_svm.cpu_cr3 = value; |
---|
1718 | break; |
---|
1719 | } |
---|
1720 | |
---|
1721 | /* We make a new one if the shadow does not exist. */ |
---|
1722 | if ( value == v->arch.hvm_svm.cpu_cr3 ) |
---|
1723 | { |
---|
1724 | /* |
---|
1725 | * This is simple TLB flush, implying the guest has |
---|
1726 | * removed some translation or changed page attributes. |
---|
1727 | * We simply invalidate the shadow. |
---|
1728 | */ |
---|
1729 | mfn = get_mfn_from_gpfn(value >> PAGE_SHIFT); |
---|
1730 | if ( mfn != pagetable_get_pfn(v->arch.guest_table) ) |
---|
1731 | goto bad_cr3; |
---|
1732 | paging_update_cr3(v); |
---|
1733 | } |
---|
1734 | else |
---|
1735 | { |
---|
1736 | /* |
---|
1737 | * If different, make a shadow. Check if the PDBR is valid |
---|
1738 | * first. |
---|
1739 | */ |
---|
1740 | HVM_DBG_LOG(DBG_LEVEL_VMMU, "CR3 value = %lx", value); |
---|
1741 | mfn = get_mfn_from_gpfn(value >> PAGE_SHIFT); |
---|
1742 | if ( !mfn_valid(mfn) || !get_page(mfn_to_page(mfn), v->domain) ) |
---|
1743 | goto bad_cr3; |
---|
1744 | |
---|
1745 | old_base_mfn = pagetable_get_pfn(v->arch.guest_table); |
---|
1746 | v->arch.guest_table = pagetable_from_pfn(mfn); |
---|
1747 | |
---|
1748 | if ( old_base_mfn ) |
---|
1749 | put_page(mfn_to_page(old_base_mfn)); |
---|
1750 | |
---|
1751 | v->arch.hvm_svm.cpu_cr3 = value; |
---|
1752 | update_cr3(v); |
---|
1753 | HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx", value); |
---|
1754 | } |
---|
1755 | break; |
---|
1756 | |
---|
1757 | case 4: /* CR4 */ |
---|
1758 | if ( paging_mode_hap(v->domain) ) |
---|
1759 | { |
---|
1760 | vmcb->cr4 = v->arch.hvm_svm.cpu_shadow_cr4 = value; |
---|
1761 | paging_update_paging_modes(v); |
---|
1762 | break; |
---|
1763 | } |
---|
1764 | |
---|
1765 | old_cr = v->arch.hvm_svm.cpu_shadow_cr4; |
---|
1766 | if ( value & X86_CR4_PAE && !(old_cr & X86_CR4_PAE) ) |
---|
1767 | { |
---|
1768 | if ( svm_pgbit_test(v) ) |
---|
1769 | { |
---|
1770 | /* The guest is a 32-bit PAE guest. */ |
---|
1771 | #if CONFIG_PAGING_LEVELS >= 3 |
---|
1772 | unsigned long mfn, old_base_mfn; |
---|
1773 | mfn = get_mfn_from_gpfn(v->arch.hvm_svm.cpu_cr3 >> PAGE_SHIFT); |
---|
1774 | if ( !mfn_valid(mfn) || |
---|
1775 | !get_page(mfn_to_page(mfn), v->domain) ) |
---|
1776 | goto bad_cr3; |
---|
1777 | |
---|
1778 | /* |
---|
1779 | * Now arch.guest_table points to machine physical. |
---|
1780 | */ |
---|
1781 | |
---|
1782 | old_base_mfn = pagetable_get_pfn(v->arch.guest_table); |
---|
1783 | v->arch.guest_table = pagetable_from_pfn(mfn); |
---|
1784 | if ( old_base_mfn ) |
---|
1785 | put_page(mfn_to_page(old_base_mfn)); |
---|
1786 | paging_update_paging_modes(v); |
---|
1787 | |
---|
1788 | HVM_DBG_LOG(DBG_LEVEL_VMMU, "New arch.guest_table = %lx", |
---|
1789 | (unsigned long) (mfn << PAGE_SHIFT)); |
---|
1790 | |
---|
1791 | HVM_DBG_LOG(DBG_LEVEL_VMMU, |
---|
1792 | "Update CR3 value = %lx, mfn = %lx", |
---|
1793 | v->arch.hvm_svm.cpu_cr3, mfn); |
---|
1794 | #endif |
---|
1795 | } |
---|
1796 | } |
---|
1797 | else if ( !(value & X86_CR4_PAE) ) |
---|
1798 | { |
---|
1799 | if ( svm_long_mode_enabled(v) ) |
---|
1800 | { |
---|
1801 | svm_inject_exception(v, TRAP_gp_fault, 1, 0); |
---|
1802 | } |
---|
1803 | } |
---|
1804 | |
---|
1805 | v->arch.hvm_svm.cpu_shadow_cr4 = value; |
---|
1806 | vmcb->cr4 = value | SVM_CR4_HOST_MASK; |
---|
1807 | |
---|
1808 | /* |
---|
1809 | * Writing to CR4 to modify the PSE, PGE, or PAE flag invalidates |
---|
1810 | * all TLB entries except global entries. |
---|
1811 | */ |
---|
1812 | if ((old_cr ^ value) & (X86_CR4_PSE | X86_CR4_PGE | X86_CR4_PAE)) |
---|
1813 | paging_update_paging_modes(v); |
---|
1814 | break; |
---|
1815 | |
---|
1816 | case 8: |
---|
1817 | vlapic_set_reg(vlapic, APIC_TASKPRI, ((value & 0x0F) << 4)); |
---|
1818 | vmcb->vintr.fields.tpr = value & 0x0F; |
---|
1819 | break; |
---|
1820 | |
---|
1821 | default: |
---|
1822 | gdprintk(XENLOG_ERR, "invalid cr: %d\n", cr); |
---|
1823 | domain_crash(v->domain); |
---|
1824 | return 0; |
---|
1825 | } |
---|
1826 | |
---|
1827 | return 1; |
---|
1828 | |
---|
1829 | bad_cr3: |
---|
1830 | gdprintk(XENLOG_ERR, "Invalid CR3\n"); |
---|
1831 | domain_crash(v->domain); |
---|
1832 | return 0; |
---|
1833 | } |
---|
1834 | |
---|
1835 | |
---|
1836 | #define ARR_SIZE(x) (sizeof(x) / sizeof(x[0])) |
---|
1837 | |
---|
1838 | |
---|
1839 | static int svm_cr_access(struct vcpu *v, unsigned int cr, unsigned int type, |
---|
1840 | struct cpu_user_regs *regs) |
---|
1841 | { |
---|
1842 | struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; |
---|
1843 | int inst_len = 0; |
---|
1844 | int index,addr_size,i; |
---|
1845 | unsigned int gpreg,offset; |
---|
1846 | unsigned long value,addr; |
---|
1847 | u8 buffer[MAX_INST_LEN]; |
---|
1848 | u8 prefix = 0; |
---|
1849 | u8 modrm; |
---|
1850 | enum x86_segment seg; |
---|
1851 | int result = 1; |
---|
1852 | enum instruction_index list_a[] = {INSTR_MOV2CR, INSTR_CLTS, INSTR_LMSW}; |
---|
1853 | enum instruction_index list_b[] = {INSTR_MOVCR2, INSTR_SMSW}; |
---|
1854 | enum instruction_index match; |
---|
1855 | |
---|
1856 | inst_copy_from_guest(buffer, svm_rip2pointer(v), sizeof(buffer)); |
---|
1857 | |
---|
1858 | /* get index to first actual instruction byte - as we will need to know |
---|
1859 | where the prefix lives later on */ |
---|
1860 | index = skip_prefix_bytes(buffer, sizeof(buffer)); |
---|
1861 | |
---|
1862 | if ( type == TYPE_MOV_TO_CR ) |
---|
1863 | { |
---|
1864 | inst_len = __get_instruction_length_from_list( |
---|
1865 | v, list_a, ARR_SIZE(list_a), &buffer[index], &match); |
---|
1866 | } |
---|
1867 | else /* type == TYPE_MOV_FROM_CR */ |
---|
1868 | { |
---|
1869 | inst_len = __get_instruction_length_from_list( |
---|
1870 | v, list_b, ARR_SIZE(list_b), &buffer[index], &match); |
---|
1871 | } |
---|
1872 | |
---|
1873 | ASSERT(inst_len > 0); |
---|
1874 | |
---|
1875 | inst_len += index; |
---|
1876 | |
---|
1877 | /* Check for REX prefix - it's ALWAYS the last byte of any prefix bytes */ |
---|
1878 | if (index > 0 && (buffer[index-1] & 0xF0) == 0x40) |
---|
1879 | prefix = buffer[index-1]; |
---|
1880 | |
---|
1881 | HVM_DBG_LOG(DBG_LEVEL_1, "eip = %lx", (unsigned long) vmcb->rip); |
---|
1882 | |
---|
1883 | switch (match) |
---|
1884 | { |
---|
1885 | case INSTR_MOV2CR: |
---|
1886 | gpreg = decode_src_reg(prefix, buffer[index+2]); |
---|
1887 | result = mov_to_cr(gpreg, cr, regs); |
---|
1888 | break; |
---|
1889 | |
---|
1890 | case INSTR_MOVCR2: |
---|
1891 | gpreg = decode_src_reg(prefix, buffer[index+2]); |
---|
1892 | mov_from_cr(cr, gpreg, regs); |
---|
1893 | break; |
---|
1894 | |
---|
1895 | case INSTR_CLTS: |
---|
1896 | /* TS being cleared means that it's time to restore fpu state. */ |
---|
1897 | setup_fpu(current); |
---|
1898 | vmcb->exception_intercepts &= ~(1U << TRAP_no_device); |
---|
1899 | vmcb->cr0 &= ~X86_CR0_TS; /* clear TS */ |
---|
1900 | v->arch.hvm_svm.cpu_shadow_cr0 &= ~X86_CR0_TS; /* clear TS */ |
---|
1901 | break; |
---|
1902 | |
---|
1903 | case INSTR_LMSW: |
---|
1904 | gpreg = decode_src_reg(prefix, buffer[index+2]); |
---|
1905 | value = get_reg(gpreg, regs, vmcb) & 0xF; |
---|
1906 | value = (v->arch.hvm_svm.cpu_shadow_cr0 & ~0xF) | value; |
---|
1907 | result = svm_set_cr0(value); |
---|
1908 | break; |
---|
1909 | |
---|
1910 | case INSTR_SMSW: |
---|
1911 | value = v->arch.hvm_svm.cpu_shadow_cr0 & 0xFFFF; |
---|
1912 | modrm = buffer[index+2]; |
---|
1913 | addr_size = svm_guest_x86_mode( v ); |
---|
1914 | if ( likely((modrm & 0xC0) >> 6 == 3) ) |
---|
1915 | { |
---|
1916 | gpreg = decode_src_reg(prefix, modrm); |
---|
1917 | set_reg(gpreg, value, regs, vmcb); |
---|
1918 | } |
---|
1919 | /* |
---|
1920 | * For now, only implement decode of the offset mode, since that's the |
---|
1921 | * only mode observed in a real-world OS. This code is also making the |
---|
1922 | * assumption that we'll never hit this code in long mode. |
---|
1923 | */ |
---|
1924 | else if ( (modrm == 0x26) || (modrm == 0x25) ) |
---|
1925 | { |
---|
1926 | seg = x86_seg_ds; |
---|
1927 | i = index; |
---|
1928 | /* Segment or address size overrides? */ |
---|
1929 | while ( i-- ) |
---|
1930 | { |
---|
1931 | switch ( buffer[i] ) |
---|
1932 | { |
---|
1933 | case 0x26: seg = x86_seg_es; break; |
---|
1934 | case 0x2e: seg = x86_seg_cs; break; |
---|
1935 | case 0x36: seg = x86_seg_ss; break; |
---|
1936 | case 0x64: seg = x86_seg_fs; break; |
---|
1937 | case 0x65: seg = x86_seg_gs; break; |
---|
1938 | case 0x67: addr_size ^= 6; break; |
---|
1939 | } |
---|
1940 | } |
---|
1941 | /* Bail unless this really is a seg_base + offset case */ |
---|
1942 | if ( ((modrm == 0x26) && (addr_size == 4)) || |
---|
1943 | ((modrm == 0x25) && (addr_size == 2)) ) |
---|
1944 | { |
---|
1945 | gdprintk(XENLOG_ERR, "SMSW emulation at guest address: " |
---|
1946 | "%lx failed due to unhandled addressing mode." |
---|
1947 | "ModRM byte was: %x \n", svm_rip2pointer(v), modrm); |
---|
1948 | domain_crash(v->domain); |
---|
1949 | } |
---|
1950 | inst_len += addr_size; |
---|
1951 | offset = *(( unsigned int *) ( void *) &buffer[index + 3]); |
---|
1952 | offset = ( addr_size == 4 ) ? offset : ( offset & 0xFFFF ); |
---|
1953 | addr = hvm_get_segment_base(v, seg); |
---|
1954 | addr += offset; |
---|
1955 | hvm_copy_to_guest_virt(addr,&value,2); |
---|
1956 | } |
---|
1957 | else |
---|
1958 | { |
---|
1959 | gdprintk(XENLOG_ERR, "SMSW emulation at guest address: %lx " |
---|
1960 | "failed due to unhandled addressing mode!" |
---|
1961 | "ModRM byte was: %x \n", svm_rip2pointer(v), modrm); |
---|
1962 | domain_crash(v->domain); |
---|
1963 | } |
---|
1964 | break; |
---|
1965 | |
---|
1966 | default: |
---|
1967 | BUG(); |
---|
1968 | } |
---|
1969 | |
---|
1970 | ASSERT(inst_len); |
---|
1971 | |
---|
1972 | __update_guest_eip(vmcb, inst_len); |
---|
1973 | |
---|
1974 | return result; |
---|
1975 | } |
---|
1976 | |
---|
1977 | static inline void svm_do_msr_access( |
---|
1978 | struct vcpu *v, struct cpu_user_regs *regs) |
---|
1979 | { |
---|
1980 | struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; |
---|
1981 | int inst_len; |
---|
1982 | u64 msr_content=0; |
---|
1983 | u32 ecx = regs->ecx, eax, edx; |
---|
1984 | |
---|
1985 | HVM_DBG_LOG(DBG_LEVEL_1, "ecx=%x, eax=%x, edx=%x, exitinfo = %lx", |
---|
1986 | ecx, (u32)regs->eax, (u32)regs->edx, |
---|
1987 | (unsigned long)vmcb->exitinfo1); |
---|
1988 | |
---|
1989 | /* is it a read? */ |
---|
1990 | if (vmcb->exitinfo1 == 0) |
---|
1991 | { |
---|
1992 | switch (ecx) { |
---|
1993 | case MSR_IA32_TIME_STAMP_COUNTER: |
---|
1994 | msr_content = hvm_get_guest_time(v); |
---|
1995 | break; |
---|
1996 | case MSR_IA32_APICBASE: |
---|
1997 | msr_content = vcpu_vlapic(v)->hw.apic_base_msr; |
---|
1998 | break; |
---|
1999 | case MSR_EFER: |
---|
2000 | msr_content = v->arch.hvm_svm.cpu_shadow_efer; |
---|
2001 | break; |
---|
2002 | |
---|
2003 | default: |
---|
2004 | if ( rdmsr_hypervisor_regs(ecx, &eax, &edx) || |
---|
2005 | rdmsr_safe(ecx, eax, edx) == 0 ) |
---|
2006 | { |
---|
2007 | regs->eax = eax; |
---|
2008 | regs->edx = edx; |
---|
2009 | goto done; |
---|
2010 | } |
---|
2011 | svm_inject_exception(v, TRAP_gp_fault, 1, 0); |
---|
2012 | return; |
---|
2013 | } |
---|
2014 | regs->eax = msr_content & 0xFFFFFFFF; |
---|
2015 | regs->edx = msr_content >> 32; |
---|
2016 | |
---|
2017 | done: |
---|
2018 | HVMTRACE_2D(MSR_READ, v, ecx, msr_content); |
---|
2019 | HVM_DBG_LOG(DBG_LEVEL_1, "returns: ecx=%x, eax=%lx, edx=%lx", |
---|
2020 | ecx, (unsigned long)regs->eax, (unsigned long)regs->edx); |
---|
2021 | |
---|
2022 | inst_len = __get_instruction_length(v, INSTR_RDMSR, NULL); |
---|
2023 | } |
---|
2024 | else |
---|
2025 | { |
---|
2026 | msr_content = (u32)regs->eax | ((u64)regs->edx << 32); |
---|
2027 | |
---|
2028 | HVMTRACE_2D(MSR_WRITE, v, ecx, msr_content); |
---|
2029 | |
---|
2030 | switch (ecx) |
---|
2031 | { |
---|
2032 | case MSR_IA32_TIME_STAMP_COUNTER: |
---|
2033 | hvm_set_guest_time(v, msr_content); |
---|
2034 | pt_reset(v); |
---|
2035 | break; |
---|
2036 | case MSR_IA32_APICBASE: |
---|
2037 | vlapic_msr_set(vcpu_vlapic(v), msr_content); |
---|
2038 | break; |
---|
2039 | default: |
---|
2040 | if ( !long_mode_do_msr_write(regs) ) |
---|
2041 | wrmsr_hypervisor_regs(ecx, regs->eax, regs->edx); |
---|
2042 | break; |
---|
2043 | } |
---|
2044 | |
---|
2045 | inst_len = __get_instruction_length(v, INSTR_WRMSR, NULL); |
---|
2046 | } |
---|
2047 | |
---|
2048 | __update_guest_eip(vmcb, inst_len); |
---|
2049 | } |
---|
2050 | |
---|
2051 | static inline void svm_vmexit_do_hlt(struct vmcb_struct *vmcb) |
---|
2052 | { |
---|
2053 | __update_guest_eip(vmcb, 1); |
---|
2054 | |
---|
2055 | /* Check for interrupt not handled or new interrupt. */ |
---|
2056 | if ( (vmcb->rflags & X86_EFLAGS_IF) && |
---|
2057 | (vmcb->vintr.fields.irq || cpu_has_pending_irq(current)) ) { |
---|
2058 | HVMTRACE_1D(HLT, current, /*int pending=*/ 1); |
---|
2059 | return; |
---|
2060 | } |
---|
2061 | |
---|
2062 | HVMTRACE_1D(HLT, current, /*int pending=*/ 0); |
---|
2063 | hvm_hlt(vmcb->rflags); |
---|
2064 | } |
---|
2065 | |
---|
2066 | static void svm_vmexit_do_invd(struct vcpu *v) |
---|
2067 | { |
---|
2068 | struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; |
---|
2069 | int inst_len; |
---|
2070 | |
---|
2071 | /* Invalidate the cache - we can't really do that safely - maybe we should |
---|
2072 | * WBINVD, but I think it's just fine to completely ignore it - we should |
---|
2073 | * have cache-snooping that solves it anyways. -- Mats P. |
---|
2074 | */ |
---|
2075 | |
---|
2076 | /* Tell the user that we did this - just in case someone runs some really |
---|
2077 | * weird operating system and wants to know why it's not working... |
---|
2078 | */ |
---|
2079 | gdprintk(XENLOG_WARNING, "INVD instruction intercepted - ignored\n"); |
---|
2080 | |
---|
2081 | inst_len = __get_instruction_length(v, INSTR_INVD, NULL); |
---|
2082 | __update_guest_eip(vmcb, inst_len); |
---|
2083 | } |
---|
2084 | |
---|
2085 | void svm_handle_invlpg(const short invlpga, struct cpu_user_regs *regs) |
---|
2086 | { |
---|
2087 | struct vcpu *v = current; |
---|
2088 | u8 opcode[MAX_INST_LEN], prefix, length = MAX_INST_LEN; |
---|
2089 | unsigned long g_vaddr; |
---|
2090 | int inst_len; |
---|
2091 | struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; |
---|
2092 | |
---|
2093 | /* |
---|
2094 | * Unknown how many bytes the invlpg instruction will take. Use the |
---|
2095 | * maximum instruction length here |
---|
2096 | */ |
---|
2097 | if (inst_copy_from_guest(opcode, svm_rip2pointer(v), length) < length) |
---|
2098 | { |
---|
2099 | gdprintk(XENLOG_ERR, "Error reading memory %d bytes\n", length); |
---|
2100 | domain_crash(v->domain); |
---|
2101 | return; |
---|
2102 | } |
---|
2103 | |
---|
2104 | if (invlpga) |
---|
2105 | { |
---|
2106 | inst_len = __get_instruction_length(v, INSTR_INVLPGA, opcode); |
---|
2107 | ASSERT(inst_len > 0); |
---|
2108 | __update_guest_eip(vmcb, inst_len); |
---|
2109 | |
---|
2110 | /* |
---|
2111 | * The address is implicit on this instruction. At the moment, we don't |
---|
2112 | * use ecx (ASID) to identify individual guests pages |
---|
2113 | */ |
---|
2114 | g_vaddr = regs->eax; |
---|
2115 | } |
---|
2116 | else |
---|
2117 | { |
---|
2118 | /* What about multiple prefix codes? */ |
---|
2119 | prefix = (is_prefix(opcode[0])?opcode[0]:0); |
---|
2120 | inst_len = __get_instruction_length(v, INSTR_INVLPG, opcode); |
---|
2121 | ASSERT(inst_len > 0); |
---|
2122 | |
---|
2123 | inst_len--; |
---|
2124 | length -= inst_len; |
---|
2125 | |
---|
2126 | /* |
---|
2127 | * Decode memory operand of the instruction including ModRM, SIB, and |
---|
2128 | * displacement to get effective address and length in bytes. Assume |
---|
2129 | * the system in either 32- or 64-bit mode. |
---|
2130 | */ |
---|
2131 | g_vaddr = get_effective_addr_modrm64(regs, prefix, inst_len, |
---|
2132 | &opcode[inst_len], &length); |
---|
2133 | |
---|
2134 | inst_len += length; |
---|
2135 | __update_guest_eip (vmcb, inst_len); |
---|
2136 | } |
---|
2137 | |
---|
2138 | HVMTRACE_3D(INVLPG, v, (invlpga?1:0), g_vaddr, (invlpga?regs->ecx:0)); |
---|
2139 | |
---|
2140 | paging_invlpg(v, g_vaddr); |
---|
2141 | } |
---|
2142 | |
---|
2143 | |
---|
2144 | /* |
---|
2145 | * Reset to realmode causes execution to start at 0xF000:0xFFF0 in |
---|
2146 | * 16-bit realmode. Basically, this mimics a processor reset. |
---|
2147 | * |
---|
2148 | * returns 0 on success, non-zero otherwise |
---|
2149 | */ |
---|
2150 | static int svm_reset_to_realmode(struct vcpu *v, |
---|
2151 | struct cpu_user_regs *regs) |
---|
2152 | { |
---|
2153 | struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; |
---|
2154 | |
---|
2155 | /* clear the vmcb and user regs */ |
---|
2156 | memset(regs, 0, sizeof(struct cpu_user_regs)); |
---|
2157 | |
---|
2158 | /* VMCB Control */ |
---|
2159 | vmcb->tsc_offset = 0; |
---|
2160 | |
---|
2161 | /* VMCB State */ |
---|
2162 | vmcb->cr0 = X86_CR0_ET | X86_CR0_PG | X86_CR0_WP; |
---|
2163 | v->arch.hvm_svm.cpu_shadow_cr0 = X86_CR0_ET; |
---|
2164 | |
---|
2165 | vmcb->cr2 = 0; |
---|
2166 | vmcb->efer = EFER_SVME; |
---|
2167 | |
---|
2168 | vmcb->cr4 = SVM_CR4_HOST_MASK; |
---|
2169 | v->arch.hvm_svm.cpu_shadow_cr4 = 0; |
---|
2170 | |
---|
2171 | if ( paging_mode_hap(v->domain) ) { |
---|
2172 | vmcb->cr0 = v->arch.hvm_svm.cpu_shadow_cr0; |
---|
2173 | vmcb->cr4 = v->arch.hvm_svm.cpu_shadow_cr4; |
---|
2174 | } |
---|
2175 | |
---|
2176 | /* This will jump to ROMBIOS */ |
---|
2177 | vmcb->rip = 0xFFF0; |
---|
2178 | |
---|
2179 | /* setup the segment registers and all their hidden states */ |
---|
2180 | vmcb->cs.sel = 0xF000; |
---|
2181 | vmcb->cs.attr.bytes = 0x089b; |
---|
2182 | vmcb->cs.limit = 0xffff; |
---|
2183 | vmcb->cs.base = 0x000F0000; |
---|
2184 | |
---|
2185 | vmcb->ss.sel = 0x00; |
---|
2186 | vmcb->ss.attr.bytes = 0x0893; |
---|
2187 | vmcb->ss.limit = 0xffff; |
---|
2188 | vmcb->ss.base = 0x00; |
---|
2189 | |
---|
2190 | vmcb->ds.sel = 0x00; |
---|
2191 | vmcb->ds.attr.bytes = 0x0893; |
---|
2192 | vmcb->ds.limit = 0xffff; |
---|
2193 | vmcb->ds.base = 0x00; |
---|
2194 | |
---|
2195 | vmcb->es.sel = 0x00; |
---|
2196 | vmcb->es.attr.bytes = 0x0893; |
---|
2197 | vmcb->es.limit = 0xffff; |
---|
2198 | vmcb->es.base = 0x00; |
---|
2199 | |
---|
2200 | vmcb->fs.sel = 0x00; |
---|
2201 | vmcb->fs.attr.bytes = 0x0893; |
---|
2202 | vmcb->fs.limit = 0xffff; |
---|
2203 | vmcb->fs.base = 0x00; |
---|
2204 | |
---|
2205 | vmcb->gs.sel = 0x00; |
---|
2206 | vmcb->gs.attr.bytes = 0x0893; |
---|
2207 | vmcb->gs.limit = 0xffff; |
---|
2208 | vmcb->gs.base = 0x00; |
---|
2209 | |
---|
2210 | vmcb->ldtr.sel = 0x00; |
---|
2211 | vmcb->ldtr.attr.bytes = 0x0000; |
---|
2212 | vmcb->ldtr.limit = 0x0; |
---|
2213 | vmcb->ldtr.base = 0x00; |
---|
2214 | |
---|
2215 | vmcb->gdtr.sel = 0x00; |
---|
2216 | vmcb->gdtr.attr.bytes = 0x0000; |
---|
2217 | vmcb->gdtr.limit = 0x0; |
---|
2218 | vmcb->gdtr.base = 0x00; |
---|
2219 | |
---|
2220 | vmcb->tr.sel = 0; |
---|
2221 | vmcb->tr.attr.bytes = 0; |
---|
2222 | vmcb->tr.limit = 0x0; |
---|
2223 | vmcb->tr.base = 0; |
---|
2224 | |
---|
2225 | vmcb->idtr.sel = 0x00; |
---|
2226 | vmcb->idtr.attr.bytes = 0x0000; |
---|
2227 | vmcb->idtr.limit = 0x3ff; |
---|
2228 | vmcb->idtr.base = 0x00; |
---|
2229 | |
---|
2230 | vmcb->rax = 0; |
---|
2231 | vmcb->rsp = 0; |
---|
2232 | |
---|
2233 | return 0; |
---|
2234 | } |
---|
2235 | |
---|
2236 | asmlinkage void svm_vmexit_handler(struct cpu_user_regs *regs) |
---|
2237 | { |
---|
2238 | unsigned int exit_reason; |
---|
2239 | unsigned long eip; |
---|
2240 | struct vcpu *v = current; |
---|
2241 | struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; |
---|
2242 | int inst_len, rc; |
---|
2243 | |
---|
2244 | exit_reason = vmcb->exitcode; |
---|
2245 | save_svm_cpu_user_regs(v, regs); |
---|
2246 | |
---|
2247 | HVMTRACE_2D(VMEXIT, v, vmcb->rip, exit_reason); |
---|
2248 | |
---|
2249 | if ( unlikely(exit_reason == VMEXIT_INVALID) ) |
---|
2250 | { |
---|
2251 | svm_dump_vmcb(__func__, vmcb); |
---|
2252 | goto exit_and_crash; |
---|
2253 | } |
---|
2254 | |
---|
2255 | perfc_incra(svmexits, exit_reason); |
---|
2256 | eip = vmcb->rip; |
---|
2257 | |
---|
2258 | switch ( exit_reason ) |
---|
2259 | { |
---|
2260 | case VMEXIT_INTR: |
---|
2261 | /* Asynchronous event, handled when we STGI'd after the VMEXIT. */ |
---|
2262 | HVMTRACE_0D(INTR, v); |
---|
2263 | break; |
---|
2264 | |
---|
2265 | case VMEXIT_NMI: |
---|
2266 | /* Asynchronous event, handled when we STGI'd after the VMEXIT. */ |
---|
2267 | HVMTRACE_0D(NMI, v); |
---|
2268 | break; |
---|
2269 | |
---|
2270 | case VMEXIT_SMI: |
---|
2271 | /* Asynchronous event, handled when we STGI'd after the VMEXIT. */ |
---|
2272 | HVMTRACE_0D(SMI, v); |
---|
2273 | break; |
---|
2274 | |
---|
2275 | case VMEXIT_EXCEPTION_DB: |
---|
2276 | if ( !v->domain->debugger_attached ) |
---|
2277 | goto exit_and_crash; |
---|
2278 | domain_pause_for_debugger(); |
---|
2279 | break; |
---|
2280 | |
---|
2281 | case VMEXIT_EXCEPTION_BP: |
---|
2282 | if ( !v->domain->debugger_attached ) |
---|
2283 | goto exit_and_crash; |
---|
2284 | /* AMD Vol2, 15.11: INT3, INTO, BOUND intercepts do not update RIP. */ |
---|
2285 | inst_len = __get_instruction_length(v, INSTR_INT3, NULL); |
---|
2286 | __update_guest_eip(vmcb, inst_len); |
---|
2287 | domain_pause_for_debugger(); |
---|
2288 | break; |
---|
2289 | |
---|
2290 | case VMEXIT_EXCEPTION_NM: |
---|
2291 | svm_do_no_device_fault(vmcb); |
---|
2292 | break; |
---|
2293 | |
---|
2294 | case VMEXIT_EXCEPTION_PF: { |
---|
2295 | unsigned long va; |
---|
2296 | va = vmcb->exitinfo2; |
---|
2297 | regs->error_code = vmcb->exitinfo1; |
---|
2298 | HVM_DBG_LOG(DBG_LEVEL_VMMU, |
---|
2299 | "eax=%lx, ebx=%lx, ecx=%lx, edx=%lx, esi=%lx, edi=%lx", |
---|
2300 | (unsigned long)regs->eax, (unsigned long)regs->ebx, |
---|
2301 | (unsigned long)regs->ecx, (unsigned long)regs->edx, |
---|
2302 | (unsigned long)regs->esi, (unsigned long)regs->edi); |
---|
2303 | |
---|
2304 | if ( paging_fault(va, regs) ) |
---|
2305 | { |
---|
2306 | HVMTRACE_2D(PF_XEN, v, va, regs->error_code); |
---|
2307 | break; |
---|
2308 | } |
---|
2309 | |
---|
2310 | v->arch.hvm_svm.cpu_cr2 = vmcb->cr2 = va; |
---|
2311 | svm_inject_exception(v, TRAP_page_fault, 1, regs->error_code); |
---|
2312 | break; |
---|
2313 | } |
---|
2314 | |
---|
2315 | case VMEXIT_VINTR: |
---|
2316 | vmcb->vintr.fields.irq = 0; |
---|
2317 | vmcb->general1_intercepts &= ~GENERAL1_INTERCEPT_VINTR; |
---|
2318 | break; |
---|
2319 | |
---|
2320 | case VMEXIT_INVD: |
---|
2321 | svm_vmexit_do_invd(v); |
---|
2322 | break; |
---|
2323 | |
---|
2324 | case VMEXIT_GDTR_WRITE: |
---|
2325 | printk("WRITE to GDTR\n"); |
---|
2326 | break; |
---|
2327 | |
---|
2328 | case VMEXIT_TASK_SWITCH: |
---|
2329 | goto exit_and_crash; |
---|
2330 | |
---|
2331 | case VMEXIT_CPUID: |
---|
2332 | svm_vmexit_do_cpuid(vmcb, regs); |
---|
2333 | break; |
---|
2334 | |
---|
2335 | case VMEXIT_HLT: |
---|
2336 | svm_vmexit_do_hlt(vmcb); |
---|
2337 | break; |
---|
2338 | |
---|
2339 | case VMEXIT_INVLPG: |
---|
2340 | svm_handle_invlpg(0, regs); |
---|
2341 | break; |
---|
2342 | |
---|
2343 | case VMEXIT_INVLPGA: |
---|
2344 | svm_handle_invlpg(1, regs); |
---|
2345 | break; |
---|
2346 | |
---|
2347 | case VMEXIT_VMMCALL: |
---|
2348 | inst_len = __get_instruction_length(v, INSTR_VMCALL, NULL); |
---|
2349 | ASSERT(inst_len > 0); |
---|
2350 | HVMTRACE_1D(VMMCALL, v, regs->eax); |
---|
2351 | rc = hvm_do_hypercall(regs); |
---|
2352 | if ( rc != HVM_HCALL_preempted ) |
---|
2353 | { |
---|
2354 | __update_guest_eip(vmcb, inst_len); |
---|
2355 | if ( rc == HVM_HCALL_invalidate ) |
---|
2356 | send_invalidate_req(); |
---|
2357 | } |
---|
2358 | break; |
---|
2359 | |
---|
2360 | case VMEXIT_CR0_READ: |
---|
2361 | svm_cr_access(v, 0, TYPE_MOV_FROM_CR, regs); |
---|
2362 | break; |
---|
2363 | |
---|
2364 | case VMEXIT_CR2_READ: |
---|
2365 | svm_cr_access(v, 2, TYPE_MOV_FROM_CR, regs); |
---|
2366 | break; |
---|
2367 | |
---|
2368 | case VMEXIT_CR3_READ: |
---|
2369 | svm_cr_access(v, 3, TYPE_MOV_FROM_CR, regs); |
---|
2370 | break; |
---|
2371 | |
---|
2372 | case VMEXIT_CR4_READ: |
---|
2373 | svm_cr_access(v, 4, TYPE_MOV_FROM_CR, regs); |
---|
2374 | break; |
---|
2375 | |
---|
2376 | case VMEXIT_CR8_READ: |
---|
2377 | svm_cr_access(v, 8, TYPE_MOV_FROM_CR, regs); |
---|
2378 | break; |
---|
2379 | |
---|
2380 | case VMEXIT_CR0_WRITE: |
---|
2381 | svm_cr_access(v, 0, TYPE_MOV_TO_CR, regs); |
---|
2382 | break; |
---|
2383 | |
---|
2384 | case VMEXIT_CR2_WRITE: |
---|
2385 | svm_cr_access(v, 2, TYPE_MOV_TO_CR, regs); |
---|
2386 | break; |
---|
2387 | |
---|
2388 | case VMEXIT_CR3_WRITE: |
---|
2389 | svm_cr_access(v, 3, TYPE_MOV_TO_CR, regs); |
---|
2390 | local_flush_tlb(); |
---|
2391 | break; |
---|
2392 | |
---|
2393 | case VMEXIT_CR4_WRITE: |
---|
2394 | svm_cr_access(v, 4, TYPE_MOV_TO_CR, regs); |
---|
2395 | break; |
---|
2396 | |
---|
2397 | case VMEXIT_CR8_WRITE: |
---|
2398 | svm_cr_access(v, 8, TYPE_MOV_TO_CR, regs); |
---|
2399 | break; |
---|
2400 | |
---|
2401 | case VMEXIT_DR0_WRITE ... VMEXIT_DR7_WRITE: |
---|
2402 | svm_dr_access(v, regs); |
---|
2403 | break; |
---|
2404 | |
---|
2405 | case VMEXIT_IOIO: |
---|
2406 | svm_io_instruction(v); |
---|
2407 | break; |
---|
2408 | |
---|
2409 | case VMEXIT_MSR: |
---|
2410 | svm_do_msr_access(v, regs); |
---|
2411 | break; |
---|
2412 | |
---|
2413 | case VMEXIT_SHUTDOWN: |
---|
2414 | hvm_triple_fault(); |
---|
2415 | break; |
---|
2416 | |
---|
2417 | case VMEXIT_VMRUN: |
---|
2418 | case VMEXIT_VMLOAD: |
---|
2419 | case VMEXIT_VMSAVE: |
---|
2420 | case VMEXIT_STGI: |
---|
2421 | case VMEXIT_CLGI: |
---|
2422 | case VMEXIT_SKINIT: |
---|
2423 | /* Report "Invalid opcode" on any VM-operation except VMMCALL */ |
---|
2424 | svm_inject_exception(v, TRAP_invalid_op, 0, 0); |
---|
2425 | break; |
---|
2426 | |
---|
2427 | case VMEXIT_NPF: |
---|
2428 | regs->error_code = vmcb->exitinfo1; |
---|
2429 | if ( !svm_do_nested_pgfault(vmcb->exitinfo2, regs) ) |
---|
2430 | domain_crash(v->domain); |
---|
2431 | break; |
---|
2432 | |
---|
2433 | default: |
---|
2434 | exit_and_crash: |
---|
2435 | gdprintk(XENLOG_ERR, "unexpected VMEXIT: exit reason = 0x%x, " |
---|
2436 | "exitinfo1 = %"PRIx64", exitinfo2 = %"PRIx64"\n", |
---|
2437 | exit_reason, |
---|
2438 | (u64)vmcb->exitinfo1, (u64)vmcb->exitinfo2); |
---|
2439 | domain_crash(v->domain); |
---|
2440 | break; |
---|
2441 | } |
---|
2442 | } |
---|
2443 | |
---|
2444 | asmlinkage void svm_load_cr2(void) |
---|
2445 | { |
---|
2446 | struct vcpu *v = current; |
---|
2447 | |
---|
2448 | /* This is the last C code before the VMRUN instruction. */ |
---|
2449 | HVMTRACE_0D(VMENTRY, v); |
---|
2450 | |
---|
2451 | asm volatile ( "mov %0,%%cr2" : : "r" (v->arch.hvm_svm.cpu_cr2) ); |
---|
2452 | } |
---|
2453 | |
---|
2454 | /* |
---|
2455 | * Local variables: |
---|
2456 | * mode: C |
---|
2457 | * c-set-style: "BSD" |
---|
2458 | * c-basic-offset: 4 |
---|
2459 | * tab-width: 4 |
---|
2460 | * indent-tabs-mode: nil |
---|
2461 | * End: |
---|
2462 | */ |
---|