diff options
author | Anthony Liguori <aliguori@us.ibm.com> | 2007-09-17 15:57:50 -0400 |
---|---|---|
committer | Avi Kivity <avi@qumranet.com> | 2008-01-30 10:52:46 -0500 |
commit | 7aa81cc04781b5b99a0647ec04533599d78cd219 (patch) | |
tree | 6ac8854faf3db2bc499e2c105fdfdab95df52170 /include/linux | |
parent | aca7f96600b170e470b3056aba0ed8d7df8d330d (diff) |
KVM: Refactor hypercall infrastructure (v3)
This patch refactors the current hypercall infrastructure to better
support live migration and SMP. It eliminates the hypercall page by
trapping the UD exception that would occur if you used the wrong hypercall
instruction for the underlying architecture and replacing it with the right
one lazily.
A fall-out of this patch is that the unhandled hypercalls no longer trap to
userspace. There is very little reason though to use a hypercall to
communicate with userspace as PIO or MMIO can be used. There is no code
in tree that uses userspace hypercalls.
[avi: fix #ud injection on vmx]
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'include/linux')
-rw-r--r-- | include/linux/kvm_para.h | 159 |
1 files changed, 98 insertions, 61 deletions
diff --git a/include/linux/kvm_para.h b/include/linux/kvm_para.h index 3b292565a693..cc5dfb433706 100644 --- a/include/linux/kvm_para.h +++ b/include/linux/kvm_para.h | |||
@@ -1,73 +1,110 @@ | |||
1 | #ifndef __LINUX_KVM_PARA_H | 1 | #ifndef __LINUX_KVM_PARA_H |
2 | #define __LINUX_KVM_PARA_H | 2 | #define __LINUX_KVM_PARA_H |
3 | 3 | ||
4 | /* | 4 | /* This CPUID returns the signature 'KVMKVMKVM' in ebx, ecx, and edx. It |
5 | * Guest OS interface for KVM paravirtualization | 5 | * should be used to determine that a VM is running under KVM. |
6 | * | ||
7 | * Note: this interface is totally experimental, and is certain to change | ||
8 | * as we make progress. | ||
9 | */ | 6 | */ |
7 | #define KVM_CPUID_SIGNATURE 0x40000000 | ||
10 | 8 | ||
11 | /* | 9 | /* This CPUID returns a feature bitmap in eax. Before enabling a particular |
12 | * Per-VCPU descriptor area shared between guest and host. Writable to | 10 | * paravirtualization, the appropriate feature bit should be checked. |
13 | * both guest and host. Registered with the host by the guest when | ||
14 | * a guest acknowledges paravirtual mode. | ||
15 | * | ||
16 | * NOTE: all addresses are guest-physical addresses (gpa), to make it | ||
17 | * easier for the hypervisor to map between the various addresses. | ||
18 | */ | ||
19 | struct kvm_vcpu_para_state { | ||
20 | /* | ||
21 | * API version information for compatibility. If there's any support | ||
22 | * mismatch (too old host trying to execute too new guest) then | ||
23 | * the host will deny entry into paravirtual mode. Any other | ||
24 | * combination (new host + old guest and new host + new guest) | ||
25 | * is supposed to work - new host versions will support all old | ||
26 | * guest API versions. | ||
27 | */ | ||
28 | u32 guest_version; | ||
29 | u32 host_version; | ||
30 | u32 size; | ||
31 | u32 ret; | ||
32 | |||
33 | /* | ||
34 | * The address of the vm exit instruction (VMCALL or VMMCALL), | ||
35 | * which the host will patch according to the CPU model the | ||
36 | * VM runs on: | ||
37 | */ | ||
38 | u64 hypercall_gpa; | ||
39 | |||
40 | } __attribute__ ((aligned(PAGE_SIZE))); | ||
41 | |||
42 | #define KVM_PARA_API_VERSION 1 | ||
43 | |||
44 | /* | ||
45 | * This is used for an RDMSR's ECX parameter to probe for a KVM host. | ||
46 | * Hopefully no CPU vendor will use up this number. This is placed well | ||
47 | * out of way of the typical space occupied by CPU vendors' MSR indices, | ||
48 | * and we think (or at least hope) it wont be occupied in the future | ||
49 | * either. | ||
50 | */ | 11 | */ |
51 | #define MSR_KVM_API_MAGIC 0x87655678 | 12 | #define KVM_CPUID_FEATURES 0x40000001 |
52 | 13 | ||
53 | #define KVM_EINVAL 1 | 14 | /* Return values for hypercalls */ |
15 | #define KVM_ENOSYS 1000 | ||
54 | 16 | ||
55 | /* | 17 | #ifdef __KERNEL__ |
56 | * Hypercall calling convention: | 18 | #include <asm/processor.h> |
57 | * | 19 | |
58 | * Each hypercall may have 0-6 parameters. | 20 | /* This instruction is vmcall. On non-VT architectures, it will generate a |
59 | * | 21 | * trap that we will then rewrite to the appropriate instruction. |
60 | * 64-bit hypercall index is in RAX, goes from 0 to __NR_hypercalls-1 | 22 | */ |
61 | * | 23 | #define KVM_HYPERCALL ".byte 0x0f,0x01,0xc1" |
62 | * 64-bit parameters 1-6 are in the standard gcc x86_64 calling convention | 24 | |
63 | * order: RDI, RSI, RDX, RCX, R8, R9. | 25 | /* For KVM hypercalls, a three-byte sequence of either the vmrun or the vmmrun |
64 | * | 26 | * instruction. The hypervisor may replace it with something else but only the |
65 | * 32-bit index is EBX, parameters are: EAX, ECX, EDX, ESI, EDI, EBP. | 27 | * instructions are guaranteed to be supported. |
66 | * (the first 3 are according to the gcc regparm calling convention) | ||
67 | * | 28 | * |
68 | * No registers are clobbered by the hypercall, except that the | 29 | * Up to four arguments may be passed in rbx, rcx, rdx, and rsi respectively. |
69 | * return value is in RAX. | 30 | * The hypercall number should be placed in rax and the return value will be |
31 | * placed in rax. No other registers will be clobbered unless explicited | ||
32 | * noted by the particular hypercall. | ||
70 | */ | 33 | */ |
71 | #define __NR_hypercalls 0 | 34 | |
35 | static inline long kvm_hypercall0(unsigned int nr) | ||
36 | { | ||
37 | long ret; | ||
38 | asm volatile(KVM_HYPERCALL | ||
39 | : "=a"(ret) | ||
40 | : "a"(nr)); | ||
41 | return ret; | ||
42 | } | ||
43 | |||
44 | static inline long kvm_hypercall1(unsigned int nr, unsigned long p1) | ||
45 | { | ||
46 | long ret; | ||
47 | asm volatile(KVM_HYPERCALL | ||
48 | : "=a"(ret) | ||
49 | : "a"(nr), "b"(p1)); | ||
50 | return ret; | ||
51 | } | ||
52 | |||
53 | static inline long kvm_hypercall2(unsigned int nr, unsigned long p1, | ||
54 | unsigned long p2) | ||
55 | { | ||
56 | long ret; | ||
57 | asm volatile(KVM_HYPERCALL | ||
58 | : "=a"(ret) | ||
59 | : "a"(nr), "b"(p1), "c"(p2)); | ||
60 | return ret; | ||
61 | } | ||
62 | |||
63 | static inline long kvm_hypercall3(unsigned int nr, unsigned long p1, | ||
64 | unsigned long p2, unsigned long p3) | ||
65 | { | ||
66 | long ret; | ||
67 | asm volatile(KVM_HYPERCALL | ||
68 | : "=a"(ret) | ||
69 | : "a"(nr), "b"(p1), "c"(p2), "d"(p3)); | ||
70 | return ret; | ||
71 | } | ||
72 | |||
73 | static inline long kvm_hypercall4(unsigned int nr, unsigned long p1, | ||
74 | unsigned long p2, unsigned long p3, | ||
75 | unsigned long p4) | ||
76 | { | ||
77 | long ret; | ||
78 | asm volatile(KVM_HYPERCALL | ||
79 | : "=a"(ret) | ||
80 | : "a"(nr), "b"(p1), "c"(p2), "d"(p3), "S"(p4)); | ||
81 | return ret; | ||
82 | } | ||
83 | |||
84 | static inline int kvm_para_available(void) | ||
85 | { | ||
86 | unsigned int eax, ebx, ecx, edx; | ||
87 | char signature[13]; | ||
88 | |||
89 | cpuid(KVM_CPUID_SIGNATURE, &eax, &ebx, &ecx, &edx); | ||
90 | memcpy(signature + 0, &ebx, 4); | ||
91 | memcpy(signature + 4, &ecx, 4); | ||
92 | memcpy(signature + 8, &edx, 4); | ||
93 | signature[12] = 0; | ||
94 | |||
95 | if (strcmp(signature, "KVMKVMKVM") == 0) | ||
96 | return 1; | ||
97 | |||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | static inline int kvm_para_has_feature(unsigned int feature) | ||
102 | { | ||
103 | if (cpuid_eax(KVM_CPUID_FEATURES) & (1UL << feature)) | ||
104 | return 1; | ||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | #endif | ||
72 | 109 | ||
73 | #endif | 110 | #endif |