ia64/xen-unstable

view xen/include/asm-x86/hvm/vmx/vmx.h @ 10908:a6cb8ba24a91

[HVM] Place all APIC registers into one page in native format.
With this change we can re-use code at include/asm-x86/apicdef.h,
making the code much cleaner. Also it help for future enhancement.

This patch does not change any logic except the change to
CONTROL_REG_ACCESS_NUM, which should be 0xf for CR8 access.

Signed-off-by: Yunhong Jiang <yunhong.jiang@intel.com
author kfraser@localhost.localdomain
date Wed Aug 02 10:07:03 2006 +0100 (2006-08-02)
parents f42039dcdc81
children 986cf8354d11
line source
1 /*
2 * vmx.h: VMX Architecture related definitions
3 * Copyright (c) 2004, Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
16 * Place - Suite 330, Boston, MA 02111-1307 USA.
17 *
18 */
19 #ifndef __ASM_X86_HVM_VMX_VMX_H__
20 #define __ASM_X86_HVM_VMX_VMX_H__
22 #include <xen/sched.h>
23 #include <asm/types.h>
24 #include <asm/regs.h>
25 #include <asm/processor.h>
26 #include <asm/hvm/vmx/vmcs.h>
27 #include <asm/i387.h>
29 extern void vmx_asm_vmexit_handler(struct cpu_user_regs);
30 extern void vmx_asm_do_vmentry(void);
31 extern void vmx_intr_assist(void);
32 extern void vmx_migrate_timers(struct vcpu *v);
33 extern void arch_vmx_do_launch(struct vcpu *);
34 extern void arch_vmx_do_resume(struct vcpu *);
35 extern void set_guest_time(struct vcpu *v, u64 gtime);
37 extern unsigned int cpu_rev;
39 /*
40 * Need fill bits for SENTER
41 */
43 #define MONITOR_PIN_BASED_EXEC_CONTROLS_RESERVED_VALUE 0x00000016
45 #define MONITOR_PIN_BASED_EXEC_CONTROLS \
46 ( \
47 MONITOR_PIN_BASED_EXEC_CONTROLS_RESERVED_VALUE | \
48 PIN_BASED_EXT_INTR_MASK | \
49 PIN_BASED_NMI_EXITING \
50 )
52 #define MONITOR_CPU_BASED_EXEC_CONTROLS_RESERVED_VALUE 0x0401e172
54 #define _MONITOR_CPU_BASED_EXEC_CONTROLS \
55 ( \
56 MONITOR_CPU_BASED_EXEC_CONTROLS_RESERVED_VALUE | \
57 CPU_BASED_HLT_EXITING | \
58 CPU_BASED_INVDPG_EXITING | \
59 CPU_BASED_MWAIT_EXITING | \
60 CPU_BASED_MOV_DR_EXITING | \
61 CPU_BASED_ACTIVATE_IO_BITMAP | \
62 CPU_BASED_USE_TSC_OFFSETING \
63 )
65 #define MONITOR_CPU_BASED_EXEC_CONTROLS_IA32E_MODE \
66 ( \
67 CPU_BASED_CR8_LOAD_EXITING | \
68 CPU_BASED_CR8_STORE_EXITING \
69 )
71 #define MONITOR_VM_EXIT_CONTROLS_RESERVED_VALUE 0x0003edff
73 #define MONITOR_VM_EXIT_CONTROLS_IA32E_MODE 0x00000200
75 #define _MONITOR_VM_EXIT_CONTROLS \
76 ( \
77 MONITOR_VM_EXIT_CONTROLS_RESERVED_VALUE |\
78 VM_EXIT_ACK_INTR_ON_EXIT \
79 )
81 #if defined (__x86_64__)
82 #define MONITOR_CPU_BASED_EXEC_CONTROLS \
83 ( \
84 _MONITOR_CPU_BASED_EXEC_CONTROLS | \
85 MONITOR_CPU_BASED_EXEC_CONTROLS_IA32E_MODE \
86 )
87 #define MONITOR_VM_EXIT_CONTROLS \
88 ( \
89 _MONITOR_VM_EXIT_CONTROLS | \
90 MONITOR_VM_EXIT_CONTROLS_IA32E_MODE \
91 )
92 #else
93 #define MONITOR_CPU_BASED_EXEC_CONTROLS \
94 _MONITOR_CPU_BASED_EXEC_CONTROLS
96 #define MONITOR_VM_EXIT_CONTROLS \
97 _MONITOR_VM_EXIT_CONTROLS
98 #endif
100 #define VM_ENTRY_CONTROLS_RESERVED_VALUE 0x000011ff
101 #define VM_ENTRY_CONTROLS_IA32E_MODE 0x00000200
102 #define MONITOR_VM_ENTRY_CONTROLS VM_ENTRY_CONTROLS_RESERVED_VALUE
103 /*
104 * Exit Reasons
105 */
106 #define VMX_EXIT_REASONS_FAILED_VMENTRY 0x80000000
108 #define EXIT_REASON_EXCEPTION_NMI 0
109 #define EXIT_REASON_EXTERNAL_INTERRUPT 1
111 #define EXIT_REASON_PENDING_INTERRUPT 7
113 #define EXIT_REASON_TASK_SWITCH 9
114 #define EXIT_REASON_CPUID 10
115 #define EXIT_REASON_HLT 12
116 #define EXIT_REASON_INVLPG 14
117 #define EXIT_REASON_RDPMC 15
118 #define EXIT_REASON_RDTSC 16
119 #define EXIT_REASON_VMCALL 18
120 #define EXIT_REASON_VMCLEAR 19
121 #define EXIT_REASON_VMLAUNCH 20
122 #define EXIT_REASON_VMPTRLD 21
123 #define EXIT_REASON_VMPTRST 22
124 #define EXIT_REASON_VMREAD 23
125 #define EXIT_REASON_VMRESUME 24
126 #define EXIT_REASON_VMWRITE 25
127 #define EXIT_REASON_VMOFF 26
128 #define EXIT_REASON_VMON 27
129 #define EXIT_REASON_CR_ACCESS 28
130 #define EXIT_REASON_DR_ACCESS 29
131 #define EXIT_REASON_IO_INSTRUCTION 30
132 #define EXIT_REASON_MSR_READ 31
133 #define EXIT_REASON_MSR_WRITE 32
134 #define EXIT_REASON_MWAIT_INSTRUCTION 36
136 #define EXIT_REASON_INVALID_GUEST_STATE 33
137 #define EXIT_REASON_MSR_LOADING 34
138 #define EXIT_REASON_MACHINE_CHECK 41
141 /*
142 * Interruption-information format
143 */
144 #define INTR_INFO_VECTOR_MASK 0xff /* 7:0 */
145 #define INTR_INFO_INTR_TYPE_MASK 0x700 /* 10:8 */
146 #define INTR_INFO_DELIVER_CODE_MASK 0x800 /* 11 */
147 #define INTR_INFO_VALID_MASK 0x80000000 /* 31 */
149 #define INTR_TYPE_EXT_INTR (0 << 8) /* external interrupt */
150 #define INTR_TYPE_HW_EXCEPTION (3 << 8) /* hardware exception */
151 #define INTR_TYPE_SW_EXCEPTION (6 << 8) /* software exception */
153 /*
154 * Exit Qualifications for MOV for Control Register Access
155 */
156 #define CONTROL_REG_ACCESS_NUM 0xf /* 3:0, number of control register */
157 #define CONTROL_REG_ACCESS_TYPE 0x30 /* 5:4, access type */
158 #define CONTROL_REG_ACCESS_REG 0xf00 /* 10:8, general purpose register */
159 #define LMSW_SOURCE_DATA (0xFFFF << 16) /* 16:31 lmsw source */
160 #define REG_EAX (0 << 8)
161 #define REG_ECX (1 << 8)
162 #define REG_EDX (2 << 8)
163 #define REG_EBX (3 << 8)
164 #define REG_ESP (4 << 8)
165 #define REG_EBP (5 << 8)
166 #define REG_ESI (6 << 8)
167 #define REG_EDI (7 << 8)
168 #define REG_R8 (8 << 8)
169 #define REG_R9 (9 << 8)
170 #define REG_R10 (10 << 8)
171 #define REG_R11 (11 << 8)
172 #define REG_R12 (12 << 8)
173 #define REG_R13 (13 << 8)
174 #define REG_R14 (14 << 8)
175 #define REG_R15 (15 << 8)
177 /*
178 * Exit Qualifications for MOV for Debug Register Access
179 */
180 #define DEBUG_REG_ACCESS_NUM 0x7 /* 2:0, number of debug register */
181 #define DEBUG_REG_ACCESS_TYPE 0x10 /* 4, direction of access */
182 #define TYPE_MOV_TO_DR (0 << 4)
183 #define TYPE_MOV_FROM_DR (1 << 4)
184 #define DEBUG_REG_ACCESS_REG 0xf00 /* 11:8, general purpose register */
186 /* These bits in the CR4 are owned by the host */
187 #if CONFIG_PAGING_LEVELS >= 3
188 #define VMX_CR4_HOST_MASK (X86_CR4_VMXE | X86_CR4_PAE)
189 #else
190 #define VMX_CR4_HOST_MASK (X86_CR4_VMXE)
191 #endif
193 #define VMCALL_OPCODE ".byte 0x0f,0x01,0xc1\n"
194 #define VMCLEAR_OPCODE ".byte 0x66,0x0f,0xc7\n" /* reg/opcode: /6 */
195 #define VMLAUNCH_OPCODE ".byte 0x0f,0x01,0xc2\n"
196 #define VMPTRLD_OPCODE ".byte 0x0f,0xc7\n" /* reg/opcode: /6 */
197 #define VMPTRST_OPCODE ".byte 0x0f,0xc7\n" /* reg/opcode: /7 */
198 #define VMREAD_OPCODE ".byte 0x0f,0x78\n"
199 #define VMRESUME_OPCODE ".byte 0x0f,0x01,0xc3\n"
200 #define VMWRITE_OPCODE ".byte 0x0f,0x79\n"
201 #define VMXOFF_OPCODE ".byte 0x0f,0x01,0xc4\n"
202 #define VMXON_OPCODE ".byte 0xf3,0x0f,0xc7\n"
204 #define MODRM_EAX_06 ".byte 0x30\n" /* [EAX], with reg/opcode: /6 */
205 #define MODRM_EAX_07 ".byte 0x38\n" /* [EAX], with reg/opcode: /7 */
206 #define MODRM_EAX_ECX ".byte 0xc1\n" /* [EAX], [ECX] */
208 static inline void __vmptrld(u64 addr)
209 {
210 __asm__ __volatile__ ( VMPTRLD_OPCODE
211 MODRM_EAX_06
212 /* CF==1 or ZF==1 --> crash (ud2) */
213 "ja 1f ; ud2 ; 1:\n"
214 :
215 : "a" (&addr)
216 : "memory");
217 }
219 static inline void __vmptrst(u64 addr)
220 {
221 __asm__ __volatile__ ( VMPTRST_OPCODE
222 MODRM_EAX_07
223 :
224 : "a" (&addr)
225 : "memory");
226 }
228 static inline void __vmpclear(u64 addr)
229 {
230 __asm__ __volatile__ ( VMCLEAR_OPCODE
231 MODRM_EAX_06
232 /* CF==1 or ZF==1 --> crash (ud2) */
233 "ja 1f ; ud2 ; 1:\n"
234 :
235 : "a" (&addr)
236 : "memory");
237 }
239 #define __vmread(x, ptr) ___vmread((x), (ptr), sizeof(*(ptr)))
241 static always_inline int ___vmread(
242 const unsigned long field, void *ptr, const int size)
243 {
244 unsigned long ecx = 0;
245 int rc;
247 __asm__ __volatile__ ( VMREAD_OPCODE
248 MODRM_EAX_ECX
249 /* CF==1 or ZF==1 --> rc = -1 */
250 "setna %b0 ; neg %0"
251 : "=q" (rc), "=c" (ecx)
252 : "0" (0), "a" (field)
253 : "memory");
255 switch (size) {
256 case 1:
257 *((u8 *) (ptr)) = ecx;
258 break;
259 case 2:
260 *((u16 *) (ptr)) = ecx;
261 break;
262 case 4:
263 *((u32 *) (ptr)) = ecx;
264 break;
265 case 8:
266 *((u64 *) (ptr)) = ecx;
267 break;
268 default:
269 domain_crash_synchronous();
270 break;
271 }
273 return rc;
274 }
277 static always_inline void __vmwrite_vcpu(struct vcpu *v, unsigned long field, unsigned long value)
278 {
279 switch(field) {
280 case CR0_READ_SHADOW:
281 v->arch.hvm_vmx.cpu_shadow_cr0 = value;
282 break;
283 case GUEST_CR0:
284 v->arch.hvm_vmx.cpu_cr0 = value;
285 break;
286 case CPU_BASED_VM_EXEC_CONTROL:
287 v->arch.hvm_vmx.cpu_based_exec_control = value;
288 break;
289 default:
290 printk("__vmwrite_cpu: invalid field %lx\n", field);
291 break;
292 }
293 }
295 static always_inline void __vmread_vcpu(struct vcpu *v, unsigned long field, unsigned long *value)
296 {
297 switch(field) {
298 case CR0_READ_SHADOW:
299 *value = v->arch.hvm_vmx.cpu_shadow_cr0;
300 break;
301 case GUEST_CR0:
302 *value = v->arch.hvm_vmx.cpu_cr0;
303 break;
304 case CPU_BASED_VM_EXEC_CONTROL:
305 *value = v->arch.hvm_vmx.cpu_based_exec_control;
306 break;
307 default:
308 printk("__vmread_cpu: invalid field %lx\n", field);
309 break;
310 }
311 }
313 static inline int __vmwrite (unsigned long field, unsigned long value)
314 {
315 struct vcpu *v = current;
316 int rc;
318 __asm__ __volatile__ ( VMWRITE_OPCODE
319 MODRM_EAX_ECX
320 /* CF==1 or ZF==1 --> rc = -1 */
321 "setna %b0 ; neg %0"
322 : "=q" (rc)
323 : "0" (0), "a" (field) , "c" (value)
324 : "memory");
326 switch(field) {
327 case CR0_READ_SHADOW:
328 case GUEST_CR0:
329 case CPU_BASED_VM_EXEC_CONTROL:
330 __vmwrite_vcpu(v, field, value);
331 break;
332 }
334 return rc;
335 }
337 static inline int __vm_set_bit(unsigned long field, unsigned long mask)
338 {
339 unsigned long tmp;
340 int err = 0;
342 err |= __vmread(field, &tmp);
343 tmp |= mask;
344 err |= __vmwrite(field, tmp);
346 return err;
347 }
349 static inline int __vm_clear_bit(unsigned long field, unsigned long mask)
350 {
351 unsigned long tmp;
352 int err = 0;
354 err |= __vmread(field, &tmp);
355 tmp &= ~mask;
356 err |= __vmwrite(field, tmp);
358 return err;
359 }
361 static inline void __vmxoff (void)
362 {
363 __asm__ __volatile__ ( VMXOFF_OPCODE
364 ::: "memory");
365 }
367 static inline int __vmxon (u64 addr)
368 {
369 int rc;
371 __asm__ __volatile__ ( VMXON_OPCODE
372 MODRM_EAX_06
373 /* CF==1 or ZF==1 --> rc = -1 */
374 "setna %b0 ; neg %0"
375 : "=q" (rc)
376 : "0" (0), "a" (&addr)
377 : "memory");
379 return rc;
380 }
382 /* Make sure that xen intercepts any FP accesses from current */
383 static inline void vmx_stts(void)
384 {
385 unsigned long cr0;
386 struct vcpu *v = current;
388 /* FPU state already dirty? Then no need to setup_fpu() lazily. */
389 if ( test_bit(_VCPUF_fpu_dirtied, &v->vcpu_flags) )
390 return;
392 /*
393 * If the guest does not have TS enabled then we must cause and handle an
394 * exception on first use of the FPU. If the guest *does* have TS enabled
395 * then this is not necessary: no FPU activity can occur until the guest
396 * clears CR0.TS, and we will initialise the FPU when that happens.
397 */
398 __vmread_vcpu(v, CR0_READ_SHADOW, &cr0);
399 if ( !(cr0 & X86_CR0_TS) )
400 {
401 __vmread_vcpu(v, GUEST_CR0, &cr0);
402 __vmwrite(GUEST_CR0, cr0 | X86_CR0_TS);
403 __vm_set_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_NM);
404 }
405 }
407 /* Works only for vcpu == current */
408 static inline int vmx_paging_enabled(struct vcpu *v)
409 {
410 unsigned long cr0;
412 __vmread_vcpu(v, CR0_READ_SHADOW, &cr0);
413 return (cr0 & X86_CR0_PE) && (cr0 & X86_CR0_PG);
414 }
416 static inline int vmx_pgbit_test(struct vcpu *v)
417 {
418 unsigned long cr0;
420 __vmread_vcpu(v, CR0_READ_SHADOW, &cr0);
421 return (cr0 & X86_CR0_PG);
422 }
424 static inline int __vmx_inject_exception(struct vcpu *v, int trap, int type,
425 int error_code, int ilen)
426 {
427 unsigned long intr_fields;
429 /* Reflect it back into the guest */
430 intr_fields = (INTR_INFO_VALID_MASK | type | trap);
431 if (error_code != VMX_DELIVER_NO_ERROR_CODE) {
432 __vmwrite(VM_ENTRY_EXCEPTION_ERROR_CODE, error_code);
433 intr_fields |= INTR_INFO_DELIVER_CODE_MASK;
434 }
436 if(ilen)
437 __vmwrite(VM_ENTRY_INSTRUCTION_LEN, ilen);
439 __vmwrite(VM_ENTRY_INTR_INFO_FIELD, intr_fields);
440 return 0;
441 }
443 static inline int vmx_inject_hw_exception(struct vcpu *v, int trap, int error_code)
444 {
445 v->arch.hvm_vmx.vector_injected = 1;
446 return __vmx_inject_exception(v, trap, INTR_TYPE_HW_EXCEPTION,
447 error_code, 0);
448 }
450 static inline int vmx_inject_sw_exception(struct vcpu *v, int trap, int instruction_len) {
451 v->arch.hvm_vmx.vector_injected=1;
452 return __vmx_inject_exception(v, trap, INTR_TYPE_SW_EXCEPTION,
453 VMX_DELIVER_NO_ERROR_CODE,
454 instruction_len);
455 }
457 static inline int vmx_inject_extint(struct vcpu *v, int trap, int error_code)
458 {
459 __vmx_inject_exception(v, trap, INTR_TYPE_EXT_INTR, error_code, 0);
460 __vmwrite(GUEST_INTERRUPTIBILITY_INFO, 0);
462 return 0;
463 }
465 static inline int vmx_reflect_exception(struct vcpu *v)
466 {
467 int error_code, intr_info, vector;
469 __vmread(VM_EXIT_INTR_INFO, &intr_info);
470 vector = intr_info & 0xff;
471 if (intr_info & INTR_INFO_DELIVER_CODE_MASK)
472 __vmread(VM_EXIT_INTR_ERROR_CODE, &error_code);
473 else
474 error_code = VMX_DELIVER_NO_ERROR_CODE;
476 #ifndef NDEBUG
477 {
478 unsigned long eip;
480 __vmread(GUEST_RIP, &eip);
481 HVM_DBG_LOG(DBG_LEVEL_1,
482 "vmx_reflect_exception: eip = %lx, error_code = %x",
483 eip, error_code);
484 }
485 #endif /* NDEBUG */
487 /* According to Intel Virtualization Technology Specification for
488 the IA-32 Intel Architecture (C97063-002 April 2005), section
489 2.8.3, SW_EXCEPTION should be used for #BP and #OV, and
490 HW_EXCPEPTION used for everything else. The main difference
491 appears to be that for SW_EXCEPTION, the EIP/RIP is incremented
492 by VM_ENTER_INSTRUCTION_LEN bytes, whereas for HW_EXCEPTION,
493 it is not. */
494 if((intr_info & INTR_INFO_INTR_TYPE_MASK) == INTR_TYPE_SW_EXCEPTION) {
495 int ilen;
496 __vmread(VM_EXIT_INSTRUCTION_LEN, &ilen);
497 vmx_inject_sw_exception(v, vector, ilen);
498 } else
499 vmx_inject_hw_exception(v, vector, error_code);
500 return 0;
501 }
503 #endif /* __ASM_X86_HVM_VMX_VMX_H__ */