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