KVM: Refactor hypercall infrastructure (v3)
[safe/jmp/linux-2.6] / include / linux / kvm_para.h
1 #ifndef __LINUX_KVM_PARA_H
2 #define __LINUX_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 /* Return values for hypercalls */
15 #define KVM_ENOSYS              1000
16
17 #ifdef __KERNEL__
18 #include <asm/processor.h>
19
20 /* This instruction is vmcall.  On non-VT architectures, it will generate a
21  * trap that we will then rewrite to the appropriate instruction.
22  */
23 #define KVM_HYPERCALL ".byte 0x0f,0x01,0xc1"
24
25 /* For KVM hypercalls, a three-byte sequence of either the vmrun or the vmmrun
26  * instruction.  The hypervisor may replace it with something else but only the
27  * instructions are guaranteed to be supported.
28  *
29  * Up to four arguments may be passed in rbx, rcx, rdx, and rsi respectively.
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.
33  */
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
109
110 #endif