]> rtime.felk.cvut.cz Git - jailhouse.git/blob - hypervisor/arch/x86/include/asm/jailhouse_hypercall.h
b128447cc45c229a35f08b3e97fe1cc8a6229561
[jailhouse.git] / hypervisor / arch / x86 / include / asm / jailhouse_hypercall.h
1 /*
2  * Jailhouse, a Linux-based partitioning hypervisor
3  *
4  * Copyright (c) Siemens AG, 2013-2015
5  *
6  * Authors:
7  *  Jan Kiszka <jan.kiszka@siemens.com>
8  *
9  * This work is licensed under the terms of the GNU GPL, version 2.  See
10  * the COPYING file in the top-level directory.
11  *
12  * Alternatively, you can use or redistribute this file under the following
13  * BSD license:
14  *
15  * Redistribution and use in source and binary forms, with or without
16  * modification, are permitted provided that the following conditions
17  * are met:
18  *
19  * 1. Redistributions of source code must retain the above copyright
20  *    notice, this list of conditions and the following disclaimer.
21  *
22  * 2. Redistributions in binary form must reproduce the above copyright
23  *    notice, this list of conditions and the following disclaimer in the
24  *    documentation and/or other materials provided with the distribution.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
30  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
36  * THE POSSIBILITY OF SUCH DAMAGE.
37  */
38
39 #define JAILHOUSE_BASE          __MAKE_UL(0xfffffffff0000000)
40
41 /*
42  * As this is never called on a CPU without VM extensions,
43  * we assume that where VMCALL isn't available, VMMCALL is.
44  */
45 #define JAILHOUSE_CALL_CODE     \
46         "cmpb $0x01, %[use_vmcall]\n\t"\
47         "jne 1f\n\t"\
48         "vmcall\n\t"\
49         "jmp 2f\n\t"\
50         "1: vmmcall\n\t"\
51         "2:"
52
53 #define JAILHOUSE_CALL_RESULT   "=a" (result)
54 #define JAILHOUSE_USE_VMCALL    [use_vmcall] "m" (jailhouse_use_vmcall)
55 #define JAILHOUSE_CALL_NUM      "a" (num)
56 #define JAILHOUSE_CALL_ARG1     "D" (arg1)
57 #define JAILHOUSE_CALL_ARG2     "S" (arg2)
58
59 /* CPU statistics */
60 #define JAILHOUSE_CPU_STAT_VMEXITS_PIO          JAILHOUSE_GENERIC_CPU_STATS
61 #define JAILHOUSE_CPU_STAT_VMEXITS_XAPIC        JAILHOUSE_GENERIC_CPU_STATS + 1
62 #define JAILHOUSE_CPU_STAT_VMEXITS_CR           JAILHOUSE_GENERIC_CPU_STATS + 2
63 #define JAILHOUSE_CPU_STAT_VMEXITS_MSR          JAILHOUSE_GENERIC_CPU_STATS + 3
64 #define JAILHOUSE_CPU_STAT_VMEXITS_CPUID        JAILHOUSE_GENERIC_CPU_STATS + 4
65 #define JAILHOUSE_CPU_STAT_VMEXITS_XSETBV       JAILHOUSE_GENERIC_CPU_STATS + 5
66 #define JAILHOUSE_NUM_CPU_STATS                 JAILHOUSE_GENERIC_CPU_STATS + 6
67
68 /* CPUID interface */
69 #define JAILHOUSE_CPUID_SIGNATURE               0x40000000
70 #define JAILHOUSE_CPUID_FEATURES                0x40000001
71
72 #ifdef __ASSEMBLY__
73
74 #define __MAKE_UL(x)    x
75
76 #else /* !__ASSEMBLY__ */
77
78 #define __MAKE_UL(x)    x ## UL
79
80 /**
81  * @defgroup Hypercalls
82  *
83  * The hypercall subsystem provides an interface for cells
84  * to call into Jailhouse.
85  *
86  * @{
87  */
88
89 /**
90  * This variable selects the x86 hypercall instruction to be used by
91  * jailhouse_call(), jailhouse_call_arg1(), and jailhouse_call_arg2().
92  * A caller should define and initialize the variable before calling
93  * any of these functions.
94  *
95  * @li @c false Use AMD's VMMCALL.
96  * @li @c true Use Intel's VMCALL.
97  */
98 extern bool jailhouse_use_vmcall;
99
100 struct jailhouse_comm_region {
101         COMM_REGION_GENERIC_HEADER;
102
103         __u16 pm_timer_address;
104         __u16 num_cpus;
105 };
106
107 static inline __u32 jailhouse_call(__u32 num)
108 {
109         __u32 result;
110
111         asm volatile(JAILHOUSE_CALL_CODE
112                 : JAILHOUSE_CALL_RESULT
113                 : JAILHOUSE_USE_VMCALL, JAILHOUSE_CALL_NUM
114                 : "memory");
115         return result;
116 }
117
118 static inline __u32 jailhouse_call_arg1(__u32 num, unsigned long arg1)
119 {
120         __u32 result;
121
122         asm volatile(JAILHOUSE_CALL_CODE
123                 : JAILHOUSE_CALL_RESULT
124                 : JAILHOUSE_USE_VMCALL,
125                   JAILHOUSE_CALL_NUM, JAILHOUSE_CALL_ARG1
126                 : "memory");
127         return result;
128 }
129
130 static inline __u32 jailhouse_call_arg2(__u32 num, unsigned long arg1,
131                                         unsigned long arg2)
132 {
133         __u32 result;
134
135         asm volatile(JAILHOUSE_CALL_CODE
136                 : JAILHOUSE_CALL_RESULT
137                 : JAILHOUSE_USE_VMCALL,
138                   JAILHOUSE_CALL_NUM, JAILHOUSE_CALL_ARG1, JAILHOUSE_CALL_ARG2
139                 : "memory");
140         return result;
141 }
142
143 static inline void
144 jailhouse_send_msg_to_cell(struct jailhouse_comm_region *comm_region,
145                            __u32 msg)
146 {
147         comm_region->reply_from_cell = JAILHOUSE_MSG_NONE;
148         /* ensure reply was cleared before sending new message */
149         asm volatile("mfence" : : : "memory");
150         comm_region->msg_to_cell = msg;
151 }
152
153 static inline void
154 jailhouse_send_reply_from_cell(struct jailhouse_comm_region *comm_region,
155                                __u32 reply)
156 {
157         comm_region->msg_to_cell = JAILHOUSE_MSG_NONE;
158         /* ensure message was cleared before sending reply */
159         asm volatile("mfence" : : : "memory");
160         comm_region->reply_from_cell = reply;
161 }
162
163 /** @} **/
164
165 #endif /* !__ASSEMBLY__ */