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 "call hypercall_page + %c[offset]" \
34 : "=a" (res), "=D" (tmp__) ASM_CALL_CONSTRAINT \
35 : [offset] "i" (hcall * 32), \
36 "1" ((long)(a1)) \
37 : "memory" ); \
38 (type)res; \
39 })
40
41 #define _hypercall64_2(type, hcall, a1, a2) \
42 ({ \
43 long res, tmp__; \
44 asm volatile ( \
45 "call hypercall_page + %c[offset]" \
46 : "=a" (res), "=D" (tmp__), "=S" (tmp__) \
47 ASM_CALL_CONSTRAINT \
48 : [offset] "i" (hcall * 32), \
49 "1" ((long)(a1)), "2" ((long)(a2)) \
50 : "memory" ); \
51 (type)res; \
52 })
53
54 #define _hypercall64_3(type, hcall, a1, a2, a3) \
55 ({ \
56 long res, tmp__; \
57 asm volatile ( \
58 "call hypercall_page + %c[offset]" \
59 : "=a" (res), "=D" (tmp__), "=S" (tmp__), "=d" (tmp__) \
60 ASM_CALL_CONSTRAINT \
61 : [offset] "i" (hcall * 32), \
62 "1" ((long)(a1)), "2" ((long)(a2)), "3" ((long)(a3)) \
63 : "memory" ); \
64 (type)res; \
65 })
66
67 #define _hypercall64_4(type, hcall, a1, a2, a3, a4) \
68 ({ \
69 long res, tmp__; \
70 register long _a4 asm ("r10") = ((long)(a4)); \
71 asm volatile ( \
72 "call hypercall_page + %c[offset]" \
73 : "=a" (res), "=D" (tmp__), "=S" (tmp__), "=d" (tmp__), \
74 "=&r" (tmp__) ASM_CALL_CONSTRAINT \
75 : [offset] "i" (hcall * 32), \
76 "1" ((long)(a1)), "2" ((long)(a2)), "3" ((long)(a3)), \
77 "4" (_a4) \
78 : "memory" ); \
79 (type)res; \
80 })
81
82 /*
83 * Primitive Hypercall wrappers
84 */
xen_hypercall_sched_op(unsigned int cmd,void * arg)85 static inline long xen_hypercall_sched_op(unsigned int cmd, void *arg)
86 {
87 return _hypercall64_2(long, __HYPERVISOR_sched_op, cmd, arg);
88 }
89
xen_hypercall_memory_op(unsigned int cmd,void * arg)90 static inline long xen_hypercall_memory_op(unsigned int cmd, void *arg)
91 {
92 return _hypercall64_2(long, __HYPERVISOR_memory_op, cmd, arg);
93 }
94
xen_hypercall_vcpu_op(unsigned int cmd,unsigned int vcpu,void * arg)95 static inline int xen_hypercall_vcpu_op(unsigned int cmd, unsigned int vcpu,
96 void *arg)
97 {
98 return _hypercall64_3(long, __HYPERVISOR_vcpu_op, cmd, vcpu, arg);
99 }
100
xen_hypercall_event_channel_op(unsigned int cmd,void * arg)101 static inline long xen_hypercall_event_channel_op(unsigned int cmd, void *arg)
102 {
103 return _hypercall64_2(long, __HYPERVISOR_event_channel_op, cmd, arg);
104 }
105
xen_hypercall_grant_table_op(unsigned int cmd,void * arg,unsigned int count)106 static inline long xen_hypercall_grant_table_op(unsigned int cmd, void *arg,
107 unsigned int count)
108 {
109 return _hypercall64_3(long, __HYPERVISOR_grant_table_op, cmd, arg, count);
110 }
111
xen_hypercall_hvm_op(unsigned int op,void * arg)112 static inline long xen_hypercall_hvm_op(unsigned int op, void *arg)
113 {
114 return _hypercall64_2(long, __HYPERVISOR_hvm_op, op, arg);
115 }
116
117 /*
118 * Higher level hypercall helpers
119 */
xen_hypercall_console_write(const char * buf,unsigned int count)120 static inline void xen_hypercall_console_write(
121 const char *buf, unsigned int count)
122 {
123 (void)_hypercall64_3(long, __HYPERVISOR_console_io,
124 CONSOLEIO_write, count, buf);
125 }
126
xen_hypercall_shutdown(unsigned int reason)127 static inline long xen_hypercall_shutdown(unsigned int reason)
128 {
129 struct sched_shutdown s = { .reason = reason };
130 return xen_hypercall_sched_op(SCHEDOP_shutdown, &s);
131 }
132
xen_hypercall_evtchn_send(evtchn_port_t port)133 static inline long xen_hypercall_evtchn_send(evtchn_port_t port)
134 {
135 struct evtchn_send send = { .port = port };
136
137 return xen_hypercall_event_channel_op(EVTCHNOP_send, &send);
138 }
139
xen_hypercall_evtchn_unmask(evtchn_port_t port)140 static inline long xen_hypercall_evtchn_unmask(evtchn_port_t port)
141 {
142 struct evtchn_unmask unmask = { .port = port };
143
144 return xen_hypercall_event_channel_op(EVTCHNOP_unmask, &unmask);
145 }
146
xen_hypercall_hvm_get_param(uint32_t index,uint64_t * value)147 static inline long xen_hypercall_hvm_get_param(uint32_t index, uint64_t *value)
148 {
149 struct xen_hvm_param xhv = {
150 .domid = DOMID_SELF,
151 .index = index,
152 };
153 long ret = xen_hypercall_hvm_op(HVMOP_get_param, &xhv);
154
155 if ( ret == 0 )
156 *value = xhv.value;
157
158 return ret;
159 }
160
xen_hypercall_set_evtchn_upcall_vector(unsigned int cpu,unsigned int vector)161 static inline long xen_hypercall_set_evtchn_upcall_vector(
162 unsigned int cpu, unsigned int vector)
163 {
164 struct xen_hvm_evtchn_upcall_vector a = {
165 .vcpu = cpu,
166 .vector = vector,
167 };
168
169 return xen_hypercall_hvm_op(HVMOP_set_evtchn_upcall_vector, &a);
170 }
171
172 #else /* CONFIG_XEN_GUEST */
173
174 #include <xen/lib.h>
175
176 #include <public/sched.h>
177
xen_hypercall_console_write(const char * buf,unsigned int count)178 static inline void xen_hypercall_console_write(
179 const char *buf, unsigned int count)
180 {
181 ASSERT_UNREACHABLE();
182 }
183
xen_hypercall_shutdown(unsigned int reason)184 static inline long xen_hypercall_shutdown(unsigned int reason)
185 {
186 ASSERT_UNREACHABLE();
187 return 0;
188 }
189
190 #endif /* CONFIG_XEN_GUEST */
191 #endif /* __X86_XEN_HYPERCALL_H__ */
192
193 /*
194 * Local variables:
195 * mode: C
196 * c-file-style: "BSD"
197 * c-basic-offset: 4
198 * tab-width: 4
199 * indent-tabs-mode: nil
200 * End:
201 */
202