1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /******************************************************************************
3 * asm-x86/guest/xen-hcall.h
4 *
5 * Copyright (c) 2017 Citrix Systems Ltd.
6 */
7
8 #ifndef __X86_XEN_HYPERCALL_H__
9 #define __X86_XEN_HYPERCALL_H__
10
11 #ifdef CONFIG_XEN_GUEST
12
13 #include <xen/types.h>
14
15 #include <asm/asm_defns.h>
16
17 #include <public/xen.h>
18 #include <public/sched.h>
19 #include <public/hvm/hvm_op.h>
20
21 #include <public/vcpu.h>
22
23 /*
24 * Hypercall primatives for 64bit
25 *
26 * Inputs: %rdi, %rsi, %rdx, %r10, %r8, %r9 (arguments 1-6)
27 */
28
29 #define _hypercall64_1(type, hcall, a1) \
30 ({ \
31 long res, tmp__; \
32 asm volatile ( \
33 ALTERNATIVE_2("call early_hypercall", \
34 "vmmcall", ALT_NOT(X86_FEATURE_USE_VMCALL), \
35 "vmcall", X86_FEATURE_USE_VMCALL) \
36 : "=a" (res), "=D" (tmp__) ASM_CALL_CONSTRAINT \
37 : "0" (hcall), \
38 "1" ((long)(a1)) \
39 : "memory" ); \
40 (type)res; \
41 })
42
43 #define _hypercall64_2(type, hcall, a1, a2) \
44 ({ \
45 long res, tmp__; \
46 asm volatile ( \
47 ALTERNATIVE_2("call early_hypercall", \
48 "vmmcall", ALT_NOT(X86_FEATURE_USE_VMCALL), \
49 "vmcall", X86_FEATURE_USE_VMCALL) \
50 : "=a" (res), "=D" (tmp__), "=S" (tmp__) \
51 ASM_CALL_CONSTRAINT \
52 : "0" (hcall), \
53 "1" ((long)(a1)), "2" ((long)(a2)) \
54 : "memory" ); \
55 (type)res; \
56 })
57
58 #define _hypercall64_3(type, hcall, a1, a2, a3) \
59 ({ \
60 long res, tmp__; \
61 asm volatile ( \
62 ALTERNATIVE_2("call early_hypercall", \
63 "vmmcall", ALT_NOT(X86_FEATURE_USE_VMCALL), \
64 "vmcall", X86_FEATURE_USE_VMCALL) \
65 : "=a" (res), "=D" (tmp__), "=S" (tmp__), "=d" (tmp__) \
66 ASM_CALL_CONSTRAINT \
67 : "0" (hcall), \
68 "1" ((long)(a1)), "2" ((long)(a2)), "3" ((long)(a3)) \
69 : "memory" ); \
70 (type)res; \
71 })
72
73 #define _hypercall64_4(type, hcall, a1, a2, a3, a4) \
74 ({ \
75 long res, tmp__; \
76 register long _a4 asm ("r10") = ((long)(a4)); \
77 asm volatile ( \
78 ALTERNATIVE_2("call early_hypercall", \
79 "vmmcall", ALT_NOT(X86_FEATURE_USE_VMCALL), \
80 "vmcall", X86_FEATURE_USE_VMCALL) \
81 : "=a" (res), "=D" (tmp__), "=S" (tmp__), "=d" (tmp__), \
82 "=&r" (tmp__) ASM_CALL_CONSTRAINT \
83 : "0" (hcall), \
84 "1" ((long)(a1)), "2" ((long)(a2)), "3" ((long)(a3)), \
85 "4" (_a4) \
86 : "memory" ); \
87 (type)res; \
88 })
89
90 /*
91 * Primitive Hypercall wrappers
92 */
xen_hypercall_sched_op(unsigned int cmd,void * arg)93 static inline long xen_hypercall_sched_op(unsigned int cmd, void *arg)
94 {
95 return _hypercall64_2(long, __HYPERVISOR_sched_op, cmd, arg);
96 }
97
xen_hypercall_memory_op(unsigned int cmd,void * arg)98 static inline long xen_hypercall_memory_op(unsigned int cmd, void *arg)
99 {
100 return _hypercall64_2(long, __HYPERVISOR_memory_op, cmd, arg);
101 }
102
xen_hypercall_vcpu_op(unsigned int cmd,unsigned int vcpu,void * arg)103 static inline int xen_hypercall_vcpu_op(unsigned int cmd, unsigned int vcpu,
104 void *arg)
105 {
106 return _hypercall64_3(long, __HYPERVISOR_vcpu_op, cmd, vcpu, arg);
107 }
108
xen_hypercall_event_channel_op(unsigned int cmd,void * arg)109 static inline long xen_hypercall_event_channel_op(unsigned int cmd, void *arg)
110 {
111 return _hypercall64_2(long, __HYPERVISOR_event_channel_op, cmd, arg);
112 }
113
xen_hypercall_grant_table_op(unsigned int cmd,void * arg,unsigned int count)114 static inline long xen_hypercall_grant_table_op(unsigned int cmd, void *arg,
115 unsigned int count)
116 {
117 return _hypercall64_3(long, __HYPERVISOR_grant_table_op, cmd, arg, count);
118 }
119
xen_hypercall_hvm_op(unsigned int op,void * arg)120 static inline long xen_hypercall_hvm_op(unsigned int op, void *arg)
121 {
122 return _hypercall64_2(long, __HYPERVISOR_hvm_op, op, arg);
123 }
124
125 /*
126 * Higher level hypercall helpers
127 */
xen_hypercall_console_write(const char * buf,unsigned int count)128 static inline void xen_hypercall_console_write(
129 const char *buf, unsigned int count)
130 {
131 (void)_hypercall64_3(long, __HYPERVISOR_console_io,
132 CONSOLEIO_write, count, buf);
133 }
134
xen_hypercall_shutdown(unsigned int reason)135 static inline long xen_hypercall_shutdown(unsigned int reason)
136 {
137 struct sched_shutdown s = { .reason = reason };
138 return xen_hypercall_sched_op(SCHEDOP_shutdown, &s);
139 }
140
xen_hypercall_evtchn_send(evtchn_port_t port)141 static inline long xen_hypercall_evtchn_send(evtchn_port_t port)
142 {
143 struct evtchn_send send = { .port = port };
144
145 return xen_hypercall_event_channel_op(EVTCHNOP_send, &send);
146 }
147
xen_hypercall_evtchn_unmask(evtchn_port_t port)148 static inline long xen_hypercall_evtchn_unmask(evtchn_port_t port)
149 {
150 struct evtchn_unmask unmask = { .port = port };
151
152 return xen_hypercall_event_channel_op(EVTCHNOP_unmask, &unmask);
153 }
154
xen_hypercall_hvm_get_param(uint32_t index,uint64_t * value)155 static inline long xen_hypercall_hvm_get_param(uint32_t index, uint64_t *value)
156 {
157 struct xen_hvm_param xhv = {
158 .domid = DOMID_SELF,
159 .index = index,
160 };
161 long ret = xen_hypercall_hvm_op(HVMOP_get_param, &xhv);
162
163 if ( ret == 0 )
164 *value = xhv.value;
165
166 return ret;
167 }
168
xen_hypercall_set_evtchn_upcall_vector(unsigned int cpu,unsigned int vector)169 static inline long xen_hypercall_set_evtchn_upcall_vector(
170 unsigned int cpu, unsigned int vector)
171 {
172 struct xen_hvm_evtchn_upcall_vector a = {
173 .vcpu = cpu,
174 .vector = vector,
175 };
176
177 return xen_hypercall_hvm_op(HVMOP_set_evtchn_upcall_vector, &a);
178 }
179
180 #else /* CONFIG_XEN_GUEST */
181
182 #include <xen/lib.h>
183
184 #include <public/sched.h>
185
xen_hypercall_console_write(const char * buf,unsigned int count)186 static inline void xen_hypercall_console_write(
187 const char *buf, unsigned int count)
188 {
189 ASSERT_UNREACHABLE();
190 }
191
xen_hypercall_shutdown(unsigned int reason)192 static inline long xen_hypercall_shutdown(unsigned int reason)
193 {
194 ASSERT_UNREACHABLE();
195 return 0;
196 }
197
198 #endif /* CONFIG_XEN_GUEST */
199 #endif /* __X86_XEN_HYPERCALL_H__ */
200
201 /*
202 * Local variables:
203 * mode: C
204 * c-file-style: "BSD"
205 * c-basic-offset: 4
206 * tab-width: 4
207 * indent-tabs-mode: nil
208 * End:
209 */
210