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