diff options
Diffstat (limited to 'include/asm-x86/kvm_para.h')
-rw-r--r-- | include/asm-x86/kvm_para.h | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/include/asm-x86/kvm_para.h b/include/asm-x86/kvm_para.h new file mode 100644 index 000000000000..c6f3fd8d8c53 --- /dev/null +++ b/include/asm-x86/kvm_para.h | |||
@@ -0,0 +1,105 @@ | |||
1 | #ifndef __X86_KVM_PARA_H | ||
2 | #define __X86_KVM_PARA_H | ||
3 | |||
4 | /* This CPUID returns the signature 'KVMKVMKVM' in ebx, ecx, and edx. It | ||
5 | * should be used to determine that a VM is running under KVM. | ||
6 | */ | ||
7 | #define KVM_CPUID_SIGNATURE 0x40000000 | ||
8 | |||
9 | /* This CPUID returns a feature bitmap in eax. Before enabling a particular | ||
10 | * paravirtualization, the appropriate feature bit should be checked. | ||
11 | */ | ||
12 | #define KVM_CPUID_FEATURES 0x40000001 | ||
13 | |||
14 | #ifdef __KERNEL__ | ||
15 | #include <asm/processor.h> | ||
16 | |||
17 | /* This instruction is vmcall. On non-VT architectures, it will generate a | ||
18 | * trap that we will then rewrite to the appropriate instruction. | ||
19 | */ | ||
20 | #define KVM_HYPERCALL ".byte 0x0f,0x01,0xc1" | ||
21 | |||
22 | /* For KVM hypercalls, a three-byte sequence of either the vmrun or the vmmrun | ||
23 | * instruction. The hypervisor may replace it with something else but only the | ||
24 | * instructions are guaranteed to be supported. | ||
25 | * | ||
26 | * Up to four arguments may be passed in rbx, rcx, rdx, and rsi respectively. | ||
27 | * The hypercall number should be placed in rax and the return value will be | ||
28 | * placed in rax. No other registers will be clobbered unless explicited | ||
29 | * noted by the particular hypercall. | ||
30 | */ | ||
31 | |||
32 | static inline long kvm_hypercall0(unsigned int nr) | ||
33 | { | ||
34 | long ret; | ||
35 | asm volatile(KVM_HYPERCALL | ||
36 | : "=a"(ret) | ||
37 | : "a"(nr)); | ||
38 | return ret; | ||
39 | } | ||
40 | |||
41 | static inline long kvm_hypercall1(unsigned int nr, unsigned long p1) | ||
42 | { | ||
43 | long ret; | ||
44 | asm volatile(KVM_HYPERCALL | ||
45 | : "=a"(ret) | ||
46 | : "a"(nr), "b"(p1)); | ||
47 | return ret; | ||
48 | } | ||
49 | |||
50 | static inline long kvm_hypercall2(unsigned int nr, unsigned long p1, | ||
51 | unsigned long p2) | ||
52 | { | ||
53 | long ret; | ||
54 | asm volatile(KVM_HYPERCALL | ||
55 | : "=a"(ret) | ||
56 | : "a"(nr), "b"(p1), "c"(p2)); | ||
57 | return ret; | ||
58 | } | ||
59 | |||
60 | static inline long kvm_hypercall3(unsigned int nr, unsigned long p1, | ||
61 | unsigned long p2, unsigned long p3) | ||
62 | { | ||
63 | long ret; | ||
64 | asm volatile(KVM_HYPERCALL | ||
65 | : "=a"(ret) | ||
66 | : "a"(nr), "b"(p1), "c"(p2), "d"(p3)); | ||
67 | return ret; | ||
68 | } | ||
69 | |||
70 | static inline long kvm_hypercall4(unsigned int nr, unsigned long p1, | ||
71 | unsigned long p2, unsigned long p3, | ||
72 | unsigned long p4) | ||
73 | { | ||
74 | long ret; | ||
75 | asm volatile(KVM_HYPERCALL | ||
76 | : "=a"(ret) | ||
77 | : "a"(nr), "b"(p1), "c"(p2), "d"(p3), "S"(p4)); | ||
78 | return ret; | ||
79 | } | ||
80 | |||
81 | static inline int kvm_para_available(void) | ||
82 | { | ||
83 | unsigned int eax, ebx, ecx, edx; | ||
84 | char signature[13]; | ||
85 | |||
86 | cpuid(KVM_CPUID_SIGNATURE, &eax, &ebx, &ecx, &edx); | ||
87 | memcpy(signature + 0, &ebx, 4); | ||
88 | memcpy(signature + 4, &ecx, 4); | ||
89 | memcpy(signature + 8, &edx, 4); | ||
90 | signature[12] = 0; | ||
91 | |||
92 | if (strcmp(signature, "KVMKVMKVM") == 0) | ||
93 | return 1; | ||
94 | |||
95 | return 0; | ||
96 | } | ||
97 | |||
98 | static inline unsigned int kvm_arch_para_features(void) | ||
99 | { | ||
100 | return cpuid_eax(KVM_CPUID_FEATURES); | ||
101 | } | ||
102 | |||
103 | #endif | ||
104 | |||
105 | #endif | ||