Commit | Line | Data |
---|---|---|
102d8325 IM |
1 | #ifndef __LINUX_KVM_PARA_H |
2 | #define __LINUX_KVM_PARA_H | |
3 | ||
7aa81cc0 AL |
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. | |
102d8325 | 6 | */ |
7aa81cc0 | 7 | #define KVM_CPUID_SIGNATURE 0x40000000 |
102d8325 | 8 | |
7aa81cc0 AL |
9 | /* This CPUID returns a feature bitmap in eax. Before enabling a particular |
10 | * paravirtualization, the appropriate feature bit should be checked. | |
102d8325 | 11 | */ |
7aa81cc0 | 12 | #define KVM_CPUID_FEATURES 0x40000001 |
102d8325 | 13 | |
7aa81cc0 AL |
14 | /* Return values for hypercalls */ |
15 | #define KVM_ENOSYS 1000 | |
102d8325 | 16 | |
7aa81cc0 AL |
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. | |
c21415e8 | 28 | * |
7aa81cc0 AL |
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. | |
c21415e8 | 33 | */ |
7aa81cc0 AL |
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 | |
c21415e8 | 109 | |
102d8325 | 110 | #endif |