]> rtime.felk.cvut.cz Git - jailhouse.git/blob - hypervisor/arch/x86/include/asm/jailhouse_hypercall.h
Documentation: Improve hypercall subsystem description
[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 Hypercall Subsystem
82  *
83  * The hypercall subsystem provides an interface for cells to invoke Jailhouse
84  * services and interact via the communication region.
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 #ifdef DOXYGEN_CPP
101 /* included to expand COMM_REGION_GENERIC_HEADER */
102 #include <jailhouse/hypercall.h>
103 #endif
104
105 /** Communication region between hypervisor and a cell. */
106 struct jailhouse_comm_region {
107         COMM_REGION_GENERIC_HEADER;
108
109         /** I/O port address of the PM timer (x86-specific). */
110         __u16 pm_timer_address;
111         /** Number of CPUs available to the cell (x86-specific). */
112         __u16 num_cpus;
113 };
114
115 /**
116  * Invoke a hypervisor without additional arguments.
117  * @param num           Hypercall number.
118  *
119  * @return Result of the hypercall, semantic depends on the invoked service.
120  */
121 static inline __u32 jailhouse_call(__u32 num)
122 {
123         __u32 result;
124
125         asm volatile(JAILHOUSE_CALL_CODE
126                 : JAILHOUSE_CALL_RESULT
127                 : JAILHOUSE_USE_VMCALL, JAILHOUSE_CALL_NUM
128                 : "memory");
129         return result;
130 }
131
132 /**
133  * Invoke a hypervisor with one argument.
134  * @param num           Hypercall number.
135  * @param arg1          First argument.
136  *
137  * @return Result of the hypercall, semantic depends on the invoked service.
138  */
139 static inline __u32 jailhouse_call_arg1(__u32 num, unsigned long arg1)
140 {
141         __u32 result;
142
143         asm volatile(JAILHOUSE_CALL_CODE
144                 : JAILHOUSE_CALL_RESULT
145                 : JAILHOUSE_USE_VMCALL,
146                   JAILHOUSE_CALL_NUM, JAILHOUSE_CALL_ARG1
147                 : "memory");
148         return result;
149 }
150
151 /**
152  * Invoke a hypervisor with two arguments.
153  * @param num           Hypercall number.
154  * @param arg1          First argument.
155  * @param arg2          Second argument.
156  *
157  * @return Result of the hypercall, semantic depends on the invoked service.
158  */
159 static inline __u32 jailhouse_call_arg2(__u32 num, unsigned long arg1,
160                                         unsigned long arg2)
161 {
162         __u32 result;
163
164         asm volatile(JAILHOUSE_CALL_CODE
165                 : JAILHOUSE_CALL_RESULT
166                 : JAILHOUSE_USE_VMCALL,
167                   JAILHOUSE_CALL_NUM, JAILHOUSE_CALL_ARG1, JAILHOUSE_CALL_ARG2
168                 : "memory");
169         return result;
170 }
171
172 /**
173  * Send a message from the hypervisor to a cell via the communication region.
174  * @param comm_region   Pointer to Communication Region.
175  * @param msg           Message to be sent.
176  */
177 static inline void
178 jailhouse_send_msg_to_cell(struct jailhouse_comm_region *comm_region,
179                            __u32 msg)
180 {
181         comm_region->reply_from_cell = JAILHOUSE_MSG_NONE;
182         /* ensure reply was cleared before sending new message */
183         asm volatile("mfence" : : : "memory");
184         comm_region->msg_to_cell = msg;
185 }
186
187 /**
188  * Send a reply message from a cell to the hypervisor via the communication
189  * region.
190  * @param comm_region   Pointer to Communication Region.
191  * @param reply         Reply to be sent.
192  */
193 static inline void
194 jailhouse_send_reply_from_cell(struct jailhouse_comm_region *comm_region,
195                                __u32 reply)
196 {
197         comm_region->msg_to_cell = JAILHOUSE_MSG_NONE;
198         /* ensure message was cleared before sending reply */
199         asm volatile("mfence" : : : "memory");
200         comm_region->reply_from_cell = reply;
201 }
202
203 /** @} **/
204
205 #endif /* !__ASSEMBLY__ */