Back to home page

OSCL-LXR

 
 

    


0001 /******************************************************************************
0002  * hypercall.h
0003  *
0004  * Linux-specific hypervisor handling.
0005  *
0006  * Copyright (c) 2002-2004, K A Fraser
0007  *
0008  * This program is free software; you can redistribute it and/or
0009  * modify it under the terms of the GNU General Public License version 2
0010  * as published by the Free Software Foundation; or, when distributed
0011  * separately from the Linux kernel or incorporated into other
0012  * software packages, subject to the following license:
0013  *
0014  * Permission is hereby granted, free of charge, to any person obtaining a copy
0015  * of this source file (the "Software"), to deal in the Software without
0016  * restriction, including without limitation the rights to use, copy, modify,
0017  * merge, publish, distribute, sublicense, and/or sell copies of the Software,
0018  * and to permit persons to whom the Software is furnished to do so, subject to
0019  * the following conditions:
0020  *
0021  * The above copyright notice and this permission notice shall be included in
0022  * all copies or substantial portions of the Software.
0023  *
0024  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0025  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0026  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
0027  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
0028  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
0029  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
0030  * IN THE SOFTWARE.
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  * The hypercall asms have to meet several constraints:
0059  * - Work on 32- and 64-bit.
0060  *    The two architectures put their arguments in different sets of
0061  *    registers.
0062  *
0063  * - Work around asm syntax quirks
0064  *    It isn't possible to specify one of the rNN registers in a
0065  *    constraint, so we use explicit register variables to get the
0066  *    args into the right place.
0067  *
0068  * - Mark all registers as potentially clobbered
0069  *    Even unused parameters can be clobbered by the hypervisor, so we
0070  *    need to make sure gcc knows it.
0071  *
0072  * - Avoid compiler bugs.
0073  *    This is the tricky part.  Because x86_32 has such a constrained
0074  *    register set, gcc versions below 4.3 have trouble generating
0075  *    code when all the arg registers and memory are trashed by the
0076  *    asm.  There are syntactically simpler ways of achieving the
0077  *    semantics below, but they cause the compiler to crash.
0078  *
0079  *    The only combination I found which works is:
0080  *     - assign the __argX variables first
0081  *     - list all actually used parameters as "+r" (__argX)
0082  *     - clobber the rest
0083  *
0084  * The result certainly isn't pretty, and it really shows up cpp's
0085  * weakness as a macro language.  Sorry.  (But let's just give thanks
0086  * there aren't more than 5 arguments...)
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      * Suppress objtool seeing the STAC/CLAC and getting confused about it
0224      * calling random code with AC=1.
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      * For a PV guest the tools require that the start_info mfn be
0474      * present in rdx/edx when the hypercall is made. Per the
0475      * hypercall calling convention this is the third hypercall
0476      * argument, which is start_info_mfn here.
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 /* _ASM_X86_XEN_HYPERCALL_H */