0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033 #ifndef _ASM_X86_XEN_HYPERCALL_H
0034 #define _ASM_X86_XEN_HYPERCALL_H
0035
0036 #include <linux/kernel.h>
0037 #include <linux/spinlock.h>
0038 #include <linux/errno.h>
0039 #include <linux/string.h>
0040 #include <linux/types.h>
0041 #include <linux/pgtable.h>
0042
0043 #include <trace/events/xen.h>
0044
0045 #include <asm/page.h>
0046 #include <asm/smap.h>
0047 #include <asm/nospec-branch.h>
0048
0049 #include <xen/interface/xen.h>
0050 #include <xen/interface/sched.h>
0051 #include <xen/interface/physdev.h>
0052 #include <xen/interface/platform.h>
0053 #include <xen/interface/xen-mca.h>
0054
0055 struct xen_dm_op_buf;
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089 extern struct { char _entry[32]; } hypercall_page[];
0090
0091 #define __HYPERCALL "call hypercall_page+%c[offset]"
0092 #define __HYPERCALL_ENTRY(x) \
0093 [offset] "i" (__HYPERVISOR_##x * sizeof(hypercall_page[0]))
0094
0095 #ifdef CONFIG_X86_32
0096 #define __HYPERCALL_RETREG "eax"
0097 #define __HYPERCALL_ARG1REG "ebx"
0098 #define __HYPERCALL_ARG2REG "ecx"
0099 #define __HYPERCALL_ARG3REG "edx"
0100 #define __HYPERCALL_ARG4REG "esi"
0101 #define __HYPERCALL_ARG5REG "edi"
0102 #else
0103 #define __HYPERCALL_RETREG "rax"
0104 #define __HYPERCALL_ARG1REG "rdi"
0105 #define __HYPERCALL_ARG2REG "rsi"
0106 #define __HYPERCALL_ARG3REG "rdx"
0107 #define __HYPERCALL_ARG4REG "r10"
0108 #define __HYPERCALL_ARG5REG "r8"
0109 #endif
0110
0111 #define __HYPERCALL_DECLS \
0112 register unsigned long __res asm(__HYPERCALL_RETREG); \
0113 register unsigned long __arg1 asm(__HYPERCALL_ARG1REG) = __arg1; \
0114 register unsigned long __arg2 asm(__HYPERCALL_ARG2REG) = __arg2; \
0115 register unsigned long __arg3 asm(__HYPERCALL_ARG3REG) = __arg3; \
0116 register unsigned long __arg4 asm(__HYPERCALL_ARG4REG) = __arg4; \
0117 register unsigned long __arg5 asm(__HYPERCALL_ARG5REG) = __arg5;
0118
0119 #define __HYPERCALL_0PARAM "=r" (__res), ASM_CALL_CONSTRAINT
0120 #define __HYPERCALL_1PARAM __HYPERCALL_0PARAM, "+r" (__arg1)
0121 #define __HYPERCALL_2PARAM __HYPERCALL_1PARAM, "+r" (__arg2)
0122 #define __HYPERCALL_3PARAM __HYPERCALL_2PARAM, "+r" (__arg3)
0123 #define __HYPERCALL_4PARAM __HYPERCALL_3PARAM, "+r" (__arg4)
0124 #define __HYPERCALL_5PARAM __HYPERCALL_4PARAM, "+r" (__arg5)
0125
0126 #define __HYPERCALL_0ARG()
0127 #define __HYPERCALL_1ARG(a1) \
0128 __HYPERCALL_0ARG() __arg1 = (unsigned long)(a1);
0129 #define __HYPERCALL_2ARG(a1,a2) \
0130 __HYPERCALL_1ARG(a1) __arg2 = (unsigned long)(a2);
0131 #define __HYPERCALL_3ARG(a1,a2,a3) \
0132 __HYPERCALL_2ARG(a1,a2) __arg3 = (unsigned long)(a3);
0133 #define __HYPERCALL_4ARG(a1,a2,a3,a4) \
0134 __HYPERCALL_3ARG(a1,a2,a3) __arg4 = (unsigned long)(a4);
0135 #define __HYPERCALL_5ARG(a1,a2,a3,a4,a5) \
0136 __HYPERCALL_4ARG(a1,a2,a3,a4) __arg5 = (unsigned long)(a5);
0137
0138 #define __HYPERCALL_CLOBBER5 "memory"
0139 #define __HYPERCALL_CLOBBER4 __HYPERCALL_CLOBBER5, __HYPERCALL_ARG5REG
0140 #define __HYPERCALL_CLOBBER3 __HYPERCALL_CLOBBER4, __HYPERCALL_ARG4REG
0141 #define __HYPERCALL_CLOBBER2 __HYPERCALL_CLOBBER3, __HYPERCALL_ARG3REG
0142 #define __HYPERCALL_CLOBBER1 __HYPERCALL_CLOBBER2, __HYPERCALL_ARG2REG
0143 #define __HYPERCALL_CLOBBER0 __HYPERCALL_CLOBBER1, __HYPERCALL_ARG1REG
0144
0145 #define _hypercall0(type, name) \
0146 ({ \
0147 __HYPERCALL_DECLS; \
0148 __HYPERCALL_0ARG(); \
0149 asm volatile (__HYPERCALL \
0150 : __HYPERCALL_0PARAM \
0151 : __HYPERCALL_ENTRY(name) \
0152 : __HYPERCALL_CLOBBER0); \
0153 (type)__res; \
0154 })
0155
0156 #define _hypercall1(type, name, a1) \
0157 ({ \
0158 __HYPERCALL_DECLS; \
0159 __HYPERCALL_1ARG(a1); \
0160 asm volatile (__HYPERCALL \
0161 : __HYPERCALL_1PARAM \
0162 : __HYPERCALL_ENTRY(name) \
0163 : __HYPERCALL_CLOBBER1); \
0164 (type)__res; \
0165 })
0166
0167 #define _hypercall2(type, name, a1, a2) \
0168 ({ \
0169 __HYPERCALL_DECLS; \
0170 __HYPERCALL_2ARG(a1, a2); \
0171 asm volatile (__HYPERCALL \
0172 : __HYPERCALL_2PARAM \
0173 : __HYPERCALL_ENTRY(name) \
0174 : __HYPERCALL_CLOBBER2); \
0175 (type)__res; \
0176 })
0177
0178 #define _hypercall3(type, name, a1, a2, a3) \
0179 ({ \
0180 __HYPERCALL_DECLS; \
0181 __HYPERCALL_3ARG(a1, a2, a3); \
0182 asm volatile (__HYPERCALL \
0183 : __HYPERCALL_3PARAM \
0184 : __HYPERCALL_ENTRY(name) \
0185 : __HYPERCALL_CLOBBER3); \
0186 (type)__res; \
0187 })
0188
0189 #define _hypercall4(type, name, a1, a2, a3, a4) \
0190 ({ \
0191 __HYPERCALL_DECLS; \
0192 __HYPERCALL_4ARG(a1, a2, a3, a4); \
0193 asm volatile (__HYPERCALL \
0194 : __HYPERCALL_4PARAM \
0195 : __HYPERCALL_ENTRY(name) \
0196 : __HYPERCALL_CLOBBER4); \
0197 (type)__res; \
0198 })
0199
0200 static inline long
0201 xen_single_call(unsigned int call,
0202 unsigned long a1, unsigned long a2,
0203 unsigned long a3, unsigned long a4,
0204 unsigned long a5)
0205 {
0206 __HYPERCALL_DECLS;
0207 __HYPERCALL_5ARG(a1, a2, a3, a4, a5);
0208
0209 if (call >= PAGE_SIZE / sizeof(hypercall_page[0]))
0210 return -EINVAL;
0211
0212 asm volatile(CALL_NOSPEC
0213 : __HYPERCALL_5PARAM
0214 : [thunk_target] "a" (&hypercall_page[call])
0215 : __HYPERCALL_CLOBBER5);
0216
0217 return (long)__res;
0218 }
0219
0220 static __always_inline void __xen_stac(void)
0221 {
0222
0223
0224
0225
0226 asm volatile(ANNOTATE_IGNORE_ALTERNATIVE
0227 ASM_STAC ::: "memory", "flags");
0228 }
0229
0230 static __always_inline void __xen_clac(void)
0231 {
0232 asm volatile(ANNOTATE_IGNORE_ALTERNATIVE
0233 ASM_CLAC ::: "memory", "flags");
0234 }
0235
0236 static inline long
0237 privcmd_call(unsigned int call,
0238 unsigned long a1, unsigned long a2,
0239 unsigned long a3, unsigned long a4,
0240 unsigned long a5)
0241 {
0242 long res;
0243
0244 __xen_stac();
0245 res = xen_single_call(call, a1, a2, a3, a4, a5);
0246 __xen_clac();
0247
0248 return res;
0249 }
0250
0251 #ifdef CONFIG_XEN_PV
0252 static inline int
0253 HYPERVISOR_set_trap_table(struct trap_info *table)
0254 {
0255 return _hypercall1(int, set_trap_table, table);
0256 }
0257
0258 static inline int
0259 HYPERVISOR_mmu_update(struct mmu_update *req, int count,
0260 int *success_count, domid_t domid)
0261 {
0262 return _hypercall4(int, mmu_update, req, count, success_count, domid);
0263 }
0264
0265 static inline int
0266 HYPERVISOR_mmuext_op(struct mmuext_op *op, int count,
0267 int *success_count, domid_t domid)
0268 {
0269 return _hypercall4(int, mmuext_op, op, count, success_count, domid);
0270 }
0271
0272 static inline int
0273 HYPERVISOR_set_gdt(unsigned long *frame_list, int entries)
0274 {
0275 return _hypercall2(int, set_gdt, frame_list, entries);
0276 }
0277
0278 static inline int
0279 HYPERVISOR_callback_op(int cmd, void *arg)
0280 {
0281 return _hypercall2(int, callback_op, cmd, arg);
0282 }
0283
0284 static __always_inline int
0285 HYPERVISOR_set_debugreg(int reg, unsigned long value)
0286 {
0287 return _hypercall2(int, set_debugreg, reg, value);
0288 }
0289
0290 static __always_inline unsigned long
0291 HYPERVISOR_get_debugreg(int reg)
0292 {
0293 return _hypercall1(unsigned long, get_debugreg, reg);
0294 }
0295
0296 static inline int
0297 HYPERVISOR_update_descriptor(u64 ma, u64 desc)
0298 {
0299 return _hypercall2(int, update_descriptor, ma, desc);
0300 }
0301
0302 static inline int
0303 HYPERVISOR_update_va_mapping(unsigned long va, pte_t new_val,
0304 unsigned long flags)
0305 {
0306 return _hypercall3(int, update_va_mapping, va, new_val.pte, flags);
0307 }
0308
0309 static inline int
0310 HYPERVISOR_set_segment_base(int reg, unsigned long value)
0311 {
0312 return _hypercall2(int, set_segment_base, reg, value);
0313 }
0314
0315 static inline void
0316 MULTI_fpu_taskswitch(struct multicall_entry *mcl, int set)
0317 {
0318 mcl->op = __HYPERVISOR_fpu_taskswitch;
0319 mcl->args[0] = set;
0320
0321 trace_xen_mc_entry(mcl, 1);
0322 }
0323
0324 static inline void
0325 MULTI_update_va_mapping(struct multicall_entry *mcl, unsigned long va,
0326 pte_t new_val, unsigned long flags)
0327 {
0328 mcl->op = __HYPERVISOR_update_va_mapping;
0329 mcl->args[0] = va;
0330 mcl->args[1] = new_val.pte;
0331 mcl->args[2] = flags;
0332
0333 trace_xen_mc_entry(mcl, 3);
0334 }
0335
0336 static inline void
0337 MULTI_update_descriptor(struct multicall_entry *mcl, u64 maddr,
0338 struct desc_struct desc)
0339 {
0340 mcl->op = __HYPERVISOR_update_descriptor;
0341 mcl->args[0] = maddr;
0342 mcl->args[1] = *(unsigned long *)&desc;
0343
0344 trace_xen_mc_entry(mcl, 2);
0345 }
0346
0347 static inline void
0348 MULTI_mmu_update(struct multicall_entry *mcl, struct mmu_update *req,
0349 int count, int *success_count, domid_t domid)
0350 {
0351 mcl->op = __HYPERVISOR_mmu_update;
0352 mcl->args[0] = (unsigned long)req;
0353 mcl->args[1] = count;
0354 mcl->args[2] = (unsigned long)success_count;
0355 mcl->args[3] = domid;
0356
0357 trace_xen_mc_entry(mcl, 4);
0358 }
0359
0360 static inline void
0361 MULTI_mmuext_op(struct multicall_entry *mcl, struct mmuext_op *op, int count,
0362 int *success_count, domid_t domid)
0363 {
0364 mcl->op = __HYPERVISOR_mmuext_op;
0365 mcl->args[0] = (unsigned long)op;
0366 mcl->args[1] = count;
0367 mcl->args[2] = (unsigned long)success_count;
0368 mcl->args[3] = domid;
0369
0370 trace_xen_mc_entry(mcl, 4);
0371 }
0372
0373 static inline void
0374 MULTI_stack_switch(struct multicall_entry *mcl,
0375 unsigned long ss, unsigned long esp)
0376 {
0377 mcl->op = __HYPERVISOR_stack_switch;
0378 mcl->args[0] = ss;
0379 mcl->args[1] = esp;
0380
0381 trace_xen_mc_entry(mcl, 2);
0382 }
0383 #endif
0384
0385 static inline int
0386 HYPERVISOR_sched_op(int cmd, void *arg)
0387 {
0388 return _hypercall2(int, sched_op, cmd, arg);
0389 }
0390
0391 static inline long
0392 HYPERVISOR_set_timer_op(u64 timeout)
0393 {
0394 unsigned long timeout_hi = (unsigned long)(timeout>>32);
0395 unsigned long timeout_lo = (unsigned long)timeout;
0396 return _hypercall2(long, set_timer_op, timeout_lo, timeout_hi);
0397 }
0398
0399 static inline int
0400 HYPERVISOR_mca(struct xen_mc *mc_op)
0401 {
0402 mc_op->interface_version = XEN_MCA_INTERFACE_VERSION;
0403 return _hypercall1(int, mca, mc_op);
0404 }
0405
0406 static inline int
0407 HYPERVISOR_platform_op(struct xen_platform_op *op)
0408 {
0409 op->interface_version = XENPF_INTERFACE_VERSION;
0410 return _hypercall1(int, platform_op, op);
0411 }
0412
0413 static inline long
0414 HYPERVISOR_memory_op(unsigned int cmd, void *arg)
0415 {
0416 return _hypercall2(long, memory_op, cmd, arg);
0417 }
0418
0419 static inline int
0420 HYPERVISOR_multicall(void *call_list, uint32_t nr_calls)
0421 {
0422 return _hypercall2(int, multicall, call_list, nr_calls);
0423 }
0424
0425 static inline int
0426 HYPERVISOR_event_channel_op(int cmd, void *arg)
0427 {
0428 return _hypercall2(int, event_channel_op, cmd, arg);
0429 }
0430
0431 static __always_inline int
0432 HYPERVISOR_xen_version(int cmd, void *arg)
0433 {
0434 return _hypercall2(int, xen_version, cmd, arg);
0435 }
0436
0437 static inline int
0438 HYPERVISOR_console_io(int cmd, int count, char *str)
0439 {
0440 return _hypercall3(int, console_io, cmd, count, str);
0441 }
0442
0443 static inline int
0444 HYPERVISOR_physdev_op(int cmd, void *arg)
0445 {
0446 return _hypercall2(int, physdev_op, cmd, arg);
0447 }
0448
0449 static inline int
0450 HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count)
0451 {
0452 return _hypercall3(int, grant_table_op, cmd, uop, count);
0453 }
0454
0455 static inline int
0456 HYPERVISOR_vm_assist(unsigned int cmd, unsigned int type)
0457 {
0458 return _hypercall2(int, vm_assist, cmd, type);
0459 }
0460
0461 static inline int
0462 HYPERVISOR_vcpu_op(int cmd, int vcpuid, void *extra_args)
0463 {
0464 return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args);
0465 }
0466
0467 static inline int
0468 HYPERVISOR_suspend(unsigned long start_info_mfn)
0469 {
0470 struct sched_shutdown r = { .reason = SHUTDOWN_suspend };
0471
0472
0473
0474
0475
0476
0477
0478 return _hypercall3(int, sched_op, SCHEDOP_shutdown, &r, start_info_mfn);
0479 }
0480
0481 static inline unsigned long __must_check
0482 HYPERVISOR_hvm_op(int op, void *arg)
0483 {
0484 return _hypercall2(unsigned long, hvm_op, op, arg);
0485 }
0486
0487 static inline int
0488 HYPERVISOR_xenpmu_op(unsigned int op, void *arg)
0489 {
0490 return _hypercall2(int, xenpmu_op, op, arg);
0491 }
0492
0493 static inline int
0494 HYPERVISOR_dm_op(
0495 domid_t dom, unsigned int nr_bufs, struct xen_dm_op_buf *bufs)
0496 {
0497 int ret;
0498 __xen_stac();
0499 ret = _hypercall3(int, dm_op, dom, nr_bufs, bufs);
0500 __xen_clac();
0501 return ret;
0502 }
0503
0504 #endif