18c2ecf20Sopenharmony_ci/******************************************************************************
28c2ecf20Sopenharmony_ci * hypercall.h
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Linux-specific hypervisor handling.
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * Copyright (c) 2002-2004, K A Fraser
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci * This program is free software; you can redistribute it and/or
98c2ecf20Sopenharmony_ci * modify it under the terms of the GNU General Public License version 2
108c2ecf20Sopenharmony_ci * as published by the Free Software Foundation; or, when distributed
118c2ecf20Sopenharmony_ci * separately from the Linux kernel or incorporated into other
128c2ecf20Sopenharmony_ci * software packages, subject to the following license:
138c2ecf20Sopenharmony_ci *
148c2ecf20Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy
158c2ecf20Sopenharmony_ci * of this source file (the "Software"), to deal in the Software without
168c2ecf20Sopenharmony_ci * restriction, including without limitation the rights to use, copy, modify,
178c2ecf20Sopenharmony_ci * merge, publish, distribute, sublicense, and/or sell copies of the Software,
188c2ecf20Sopenharmony_ci * and to permit persons to whom the Software is furnished to do so, subject to
198c2ecf20Sopenharmony_ci * the following conditions:
208c2ecf20Sopenharmony_ci *
218c2ecf20Sopenharmony_ci * The above copyright notice and this permission notice shall be included in
228c2ecf20Sopenharmony_ci * all copies or substantial portions of the Software.
238c2ecf20Sopenharmony_ci *
248c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
258c2ecf20Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
268c2ecf20Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
278c2ecf20Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
288c2ecf20Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
298c2ecf20Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
308c2ecf20Sopenharmony_ci * IN THE SOFTWARE.
318c2ecf20Sopenharmony_ci */
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci#ifndef _ASM_X86_XEN_HYPERCALL_H
348c2ecf20Sopenharmony_ci#define _ASM_X86_XEN_HYPERCALL_H
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci#include <linux/kernel.h>
378c2ecf20Sopenharmony_ci#include <linux/spinlock.h>
388c2ecf20Sopenharmony_ci#include <linux/errno.h>
398c2ecf20Sopenharmony_ci#include <linux/string.h>
408c2ecf20Sopenharmony_ci#include <linux/types.h>
418c2ecf20Sopenharmony_ci#include <linux/pgtable.h>
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci#include <trace/events/xen.h>
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci#include <asm/page.h>
468c2ecf20Sopenharmony_ci#include <asm/smap.h>
478c2ecf20Sopenharmony_ci#include <asm/nospec-branch.h>
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci#include <xen/interface/xen.h>
508c2ecf20Sopenharmony_ci#include <xen/interface/sched.h>
518c2ecf20Sopenharmony_ci#include <xen/interface/physdev.h>
528c2ecf20Sopenharmony_ci#include <xen/interface/platform.h>
538c2ecf20Sopenharmony_ci#include <xen/interface/xen-mca.h>
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_cistruct xen_dm_op_buf;
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci/*
588c2ecf20Sopenharmony_ci * The hypercall asms have to meet several constraints:
598c2ecf20Sopenharmony_ci * - Work on 32- and 64-bit.
608c2ecf20Sopenharmony_ci *    The two architectures put their arguments in different sets of
618c2ecf20Sopenharmony_ci *    registers.
628c2ecf20Sopenharmony_ci *
638c2ecf20Sopenharmony_ci * - Work around asm syntax quirks
648c2ecf20Sopenharmony_ci *    It isn't possible to specify one of the rNN registers in a
658c2ecf20Sopenharmony_ci *    constraint, so we use explicit register variables to get the
668c2ecf20Sopenharmony_ci *    args into the right place.
678c2ecf20Sopenharmony_ci *
688c2ecf20Sopenharmony_ci * - Mark all registers as potentially clobbered
698c2ecf20Sopenharmony_ci *    Even unused parameters can be clobbered by the hypervisor, so we
708c2ecf20Sopenharmony_ci *    need to make sure gcc knows it.
718c2ecf20Sopenharmony_ci *
728c2ecf20Sopenharmony_ci * - Avoid compiler bugs.
738c2ecf20Sopenharmony_ci *    This is the tricky part.  Because x86_32 has such a constrained
748c2ecf20Sopenharmony_ci *    register set, gcc versions below 4.3 have trouble generating
758c2ecf20Sopenharmony_ci *    code when all the arg registers and memory are trashed by the
768c2ecf20Sopenharmony_ci *    asm.  There are syntactically simpler ways of achieving the
778c2ecf20Sopenharmony_ci *    semantics below, but they cause the compiler to crash.
788c2ecf20Sopenharmony_ci *
798c2ecf20Sopenharmony_ci *    The only combination I found which works is:
808c2ecf20Sopenharmony_ci *     - assign the __argX variables first
818c2ecf20Sopenharmony_ci *     - list all actually used parameters as "+r" (__argX)
828c2ecf20Sopenharmony_ci *     - clobber the rest
838c2ecf20Sopenharmony_ci *
848c2ecf20Sopenharmony_ci * The result certainly isn't pretty, and it really shows up cpp's
858c2ecf20Sopenharmony_ci * weakness as a macro language.  Sorry.  (But let's just give thanks
868c2ecf20Sopenharmony_ci * there aren't more than 5 arguments...)
878c2ecf20Sopenharmony_ci */
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ciextern struct { char _entry[32]; } hypercall_page[];
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci#define __HYPERCALL		"call hypercall_page+%c[offset]"
928c2ecf20Sopenharmony_ci#define __HYPERCALL_ENTRY(x)						\
938c2ecf20Sopenharmony_ci	[offset] "i" (__HYPERVISOR_##x * sizeof(hypercall_page[0]))
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci#ifdef CONFIG_X86_32
968c2ecf20Sopenharmony_ci#define __HYPERCALL_RETREG	"eax"
978c2ecf20Sopenharmony_ci#define __HYPERCALL_ARG1REG	"ebx"
988c2ecf20Sopenharmony_ci#define __HYPERCALL_ARG2REG	"ecx"
998c2ecf20Sopenharmony_ci#define __HYPERCALL_ARG3REG	"edx"
1008c2ecf20Sopenharmony_ci#define __HYPERCALL_ARG4REG	"esi"
1018c2ecf20Sopenharmony_ci#define __HYPERCALL_ARG5REG	"edi"
1028c2ecf20Sopenharmony_ci#else
1038c2ecf20Sopenharmony_ci#define __HYPERCALL_RETREG	"rax"
1048c2ecf20Sopenharmony_ci#define __HYPERCALL_ARG1REG	"rdi"
1058c2ecf20Sopenharmony_ci#define __HYPERCALL_ARG2REG	"rsi"
1068c2ecf20Sopenharmony_ci#define __HYPERCALL_ARG3REG	"rdx"
1078c2ecf20Sopenharmony_ci#define __HYPERCALL_ARG4REG	"r10"
1088c2ecf20Sopenharmony_ci#define __HYPERCALL_ARG5REG	"r8"
1098c2ecf20Sopenharmony_ci#endif
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci#define __HYPERCALL_DECLS						\
1128c2ecf20Sopenharmony_ci	register unsigned long __res  asm(__HYPERCALL_RETREG);		\
1138c2ecf20Sopenharmony_ci	register unsigned long __arg1 asm(__HYPERCALL_ARG1REG) = __arg1; \
1148c2ecf20Sopenharmony_ci	register unsigned long __arg2 asm(__HYPERCALL_ARG2REG) = __arg2; \
1158c2ecf20Sopenharmony_ci	register unsigned long __arg3 asm(__HYPERCALL_ARG3REG) = __arg3; \
1168c2ecf20Sopenharmony_ci	register unsigned long __arg4 asm(__HYPERCALL_ARG4REG) = __arg4; \
1178c2ecf20Sopenharmony_ci	register unsigned long __arg5 asm(__HYPERCALL_ARG5REG) = __arg5;
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ci#define __HYPERCALL_0PARAM	"=r" (__res), ASM_CALL_CONSTRAINT
1208c2ecf20Sopenharmony_ci#define __HYPERCALL_1PARAM	__HYPERCALL_0PARAM, "+r" (__arg1)
1218c2ecf20Sopenharmony_ci#define __HYPERCALL_2PARAM	__HYPERCALL_1PARAM, "+r" (__arg2)
1228c2ecf20Sopenharmony_ci#define __HYPERCALL_3PARAM	__HYPERCALL_2PARAM, "+r" (__arg3)
1238c2ecf20Sopenharmony_ci#define __HYPERCALL_4PARAM	__HYPERCALL_3PARAM, "+r" (__arg4)
1248c2ecf20Sopenharmony_ci#define __HYPERCALL_5PARAM	__HYPERCALL_4PARAM, "+r" (__arg5)
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ci#define __HYPERCALL_0ARG()
1278c2ecf20Sopenharmony_ci#define __HYPERCALL_1ARG(a1)						\
1288c2ecf20Sopenharmony_ci	__HYPERCALL_0ARG()		__arg1 = (unsigned long)(a1);
1298c2ecf20Sopenharmony_ci#define __HYPERCALL_2ARG(a1,a2)						\
1308c2ecf20Sopenharmony_ci	__HYPERCALL_1ARG(a1)		__arg2 = (unsigned long)(a2);
1318c2ecf20Sopenharmony_ci#define __HYPERCALL_3ARG(a1,a2,a3)					\
1328c2ecf20Sopenharmony_ci	__HYPERCALL_2ARG(a1,a2)		__arg3 = (unsigned long)(a3);
1338c2ecf20Sopenharmony_ci#define __HYPERCALL_4ARG(a1,a2,a3,a4)					\
1348c2ecf20Sopenharmony_ci	__HYPERCALL_3ARG(a1,a2,a3)	__arg4 = (unsigned long)(a4);
1358c2ecf20Sopenharmony_ci#define __HYPERCALL_5ARG(a1,a2,a3,a4,a5)				\
1368c2ecf20Sopenharmony_ci	__HYPERCALL_4ARG(a1,a2,a3,a4)	__arg5 = (unsigned long)(a5);
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_ci#define __HYPERCALL_CLOBBER5	"memory"
1398c2ecf20Sopenharmony_ci#define __HYPERCALL_CLOBBER4	__HYPERCALL_CLOBBER5, __HYPERCALL_ARG5REG
1408c2ecf20Sopenharmony_ci#define __HYPERCALL_CLOBBER3	__HYPERCALL_CLOBBER4, __HYPERCALL_ARG4REG
1418c2ecf20Sopenharmony_ci#define __HYPERCALL_CLOBBER2	__HYPERCALL_CLOBBER3, __HYPERCALL_ARG3REG
1428c2ecf20Sopenharmony_ci#define __HYPERCALL_CLOBBER1	__HYPERCALL_CLOBBER2, __HYPERCALL_ARG2REG
1438c2ecf20Sopenharmony_ci#define __HYPERCALL_CLOBBER0	__HYPERCALL_CLOBBER1, __HYPERCALL_ARG1REG
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_ci#define _hypercall0(type, name)						\
1468c2ecf20Sopenharmony_ci({									\
1478c2ecf20Sopenharmony_ci	__HYPERCALL_DECLS;						\
1488c2ecf20Sopenharmony_ci	__HYPERCALL_0ARG();						\
1498c2ecf20Sopenharmony_ci	asm volatile (__HYPERCALL					\
1508c2ecf20Sopenharmony_ci		      : __HYPERCALL_0PARAM				\
1518c2ecf20Sopenharmony_ci		      : __HYPERCALL_ENTRY(name)				\
1528c2ecf20Sopenharmony_ci		      : __HYPERCALL_CLOBBER0);				\
1538c2ecf20Sopenharmony_ci	(type)__res;							\
1548c2ecf20Sopenharmony_ci})
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_ci#define _hypercall1(type, name, a1)					\
1578c2ecf20Sopenharmony_ci({									\
1588c2ecf20Sopenharmony_ci	__HYPERCALL_DECLS;						\
1598c2ecf20Sopenharmony_ci	__HYPERCALL_1ARG(a1);						\
1608c2ecf20Sopenharmony_ci	asm volatile (__HYPERCALL					\
1618c2ecf20Sopenharmony_ci		      : __HYPERCALL_1PARAM				\
1628c2ecf20Sopenharmony_ci		      : __HYPERCALL_ENTRY(name)				\
1638c2ecf20Sopenharmony_ci		      : __HYPERCALL_CLOBBER1);				\
1648c2ecf20Sopenharmony_ci	(type)__res;							\
1658c2ecf20Sopenharmony_ci})
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci#define _hypercall2(type, name, a1, a2)					\
1688c2ecf20Sopenharmony_ci({									\
1698c2ecf20Sopenharmony_ci	__HYPERCALL_DECLS;						\
1708c2ecf20Sopenharmony_ci	__HYPERCALL_2ARG(a1, a2);					\
1718c2ecf20Sopenharmony_ci	asm volatile (__HYPERCALL					\
1728c2ecf20Sopenharmony_ci		      : __HYPERCALL_2PARAM				\
1738c2ecf20Sopenharmony_ci		      : __HYPERCALL_ENTRY(name)				\
1748c2ecf20Sopenharmony_ci		      : __HYPERCALL_CLOBBER2);				\
1758c2ecf20Sopenharmony_ci	(type)__res;							\
1768c2ecf20Sopenharmony_ci})
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ci#define _hypercall3(type, name, a1, a2, a3)				\
1798c2ecf20Sopenharmony_ci({									\
1808c2ecf20Sopenharmony_ci	__HYPERCALL_DECLS;						\
1818c2ecf20Sopenharmony_ci	__HYPERCALL_3ARG(a1, a2, a3);					\
1828c2ecf20Sopenharmony_ci	asm volatile (__HYPERCALL					\
1838c2ecf20Sopenharmony_ci		      : __HYPERCALL_3PARAM				\
1848c2ecf20Sopenharmony_ci		      : __HYPERCALL_ENTRY(name)				\
1858c2ecf20Sopenharmony_ci		      : __HYPERCALL_CLOBBER3);				\
1868c2ecf20Sopenharmony_ci	(type)__res;							\
1878c2ecf20Sopenharmony_ci})
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci#define _hypercall4(type, name, a1, a2, a3, a4)				\
1908c2ecf20Sopenharmony_ci({									\
1918c2ecf20Sopenharmony_ci	__HYPERCALL_DECLS;						\
1928c2ecf20Sopenharmony_ci	__HYPERCALL_4ARG(a1, a2, a3, a4);				\
1938c2ecf20Sopenharmony_ci	asm volatile (__HYPERCALL					\
1948c2ecf20Sopenharmony_ci		      : __HYPERCALL_4PARAM				\
1958c2ecf20Sopenharmony_ci		      : __HYPERCALL_ENTRY(name)				\
1968c2ecf20Sopenharmony_ci		      : __HYPERCALL_CLOBBER4);				\
1978c2ecf20Sopenharmony_ci	(type)__res;							\
1988c2ecf20Sopenharmony_ci})
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_cistatic inline long
2018c2ecf20Sopenharmony_cixen_single_call(unsigned int call,
2028c2ecf20Sopenharmony_ci		unsigned long a1, unsigned long a2,
2038c2ecf20Sopenharmony_ci		unsigned long a3, unsigned long a4,
2048c2ecf20Sopenharmony_ci		unsigned long a5)
2058c2ecf20Sopenharmony_ci{
2068c2ecf20Sopenharmony_ci	__HYPERCALL_DECLS;
2078c2ecf20Sopenharmony_ci	__HYPERCALL_5ARG(a1, a2, a3, a4, a5);
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci	if (call >= PAGE_SIZE / sizeof(hypercall_page[0]))
2108c2ecf20Sopenharmony_ci		return -EINVAL;
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ci	asm volatile(CALL_NOSPEC
2138c2ecf20Sopenharmony_ci		     : __HYPERCALL_5PARAM
2148c2ecf20Sopenharmony_ci		     : [thunk_target] "a" (&hypercall_page[call])
2158c2ecf20Sopenharmony_ci		     : __HYPERCALL_CLOBBER5);
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci	return (long)__res;
2188c2ecf20Sopenharmony_ci}
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_cistatic __always_inline void __xen_stac(void)
2218c2ecf20Sopenharmony_ci{
2228c2ecf20Sopenharmony_ci	/*
2238c2ecf20Sopenharmony_ci	 * Suppress objtool seeing the STAC/CLAC and getting confused about it
2248c2ecf20Sopenharmony_ci	 * calling random code with AC=1.
2258c2ecf20Sopenharmony_ci	 */
2268c2ecf20Sopenharmony_ci	asm volatile(ANNOTATE_IGNORE_ALTERNATIVE
2278c2ecf20Sopenharmony_ci		     ASM_STAC ::: "memory", "flags");
2288c2ecf20Sopenharmony_ci}
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_cistatic __always_inline void __xen_clac(void)
2318c2ecf20Sopenharmony_ci{
2328c2ecf20Sopenharmony_ci	asm volatile(ANNOTATE_IGNORE_ALTERNATIVE
2338c2ecf20Sopenharmony_ci		     ASM_CLAC ::: "memory", "flags");
2348c2ecf20Sopenharmony_ci}
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_cistatic inline long
2378c2ecf20Sopenharmony_ciprivcmd_call(unsigned int call,
2388c2ecf20Sopenharmony_ci	     unsigned long a1, unsigned long a2,
2398c2ecf20Sopenharmony_ci	     unsigned long a3, unsigned long a4,
2408c2ecf20Sopenharmony_ci	     unsigned long a5)
2418c2ecf20Sopenharmony_ci{
2428c2ecf20Sopenharmony_ci	long res;
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci	__xen_stac();
2458c2ecf20Sopenharmony_ci	res = xen_single_call(call, a1, a2, a3, a4, a5);
2468c2ecf20Sopenharmony_ci	__xen_clac();
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_ci	return res;
2498c2ecf20Sopenharmony_ci}
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_cistatic inline int
2528c2ecf20Sopenharmony_ciHYPERVISOR_set_trap_table(struct trap_info *table)
2538c2ecf20Sopenharmony_ci{
2548c2ecf20Sopenharmony_ci	return _hypercall1(int, set_trap_table, table);
2558c2ecf20Sopenharmony_ci}
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_cistatic inline int
2588c2ecf20Sopenharmony_ciHYPERVISOR_mmu_update(struct mmu_update *req, int count,
2598c2ecf20Sopenharmony_ci		      int *success_count, domid_t domid)
2608c2ecf20Sopenharmony_ci{
2618c2ecf20Sopenharmony_ci	return _hypercall4(int, mmu_update, req, count, success_count, domid);
2628c2ecf20Sopenharmony_ci}
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_cistatic inline int
2658c2ecf20Sopenharmony_ciHYPERVISOR_mmuext_op(struct mmuext_op *op, int count,
2668c2ecf20Sopenharmony_ci		     int *success_count, domid_t domid)
2678c2ecf20Sopenharmony_ci{
2688c2ecf20Sopenharmony_ci	return _hypercall4(int, mmuext_op, op, count, success_count, domid);
2698c2ecf20Sopenharmony_ci}
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_cistatic inline int
2728c2ecf20Sopenharmony_ciHYPERVISOR_set_gdt(unsigned long *frame_list, int entries)
2738c2ecf20Sopenharmony_ci{
2748c2ecf20Sopenharmony_ci	return _hypercall2(int, set_gdt, frame_list, entries);
2758c2ecf20Sopenharmony_ci}
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_cistatic inline int
2788c2ecf20Sopenharmony_ciHYPERVISOR_callback_op(int cmd, void *arg)
2798c2ecf20Sopenharmony_ci{
2808c2ecf20Sopenharmony_ci	return _hypercall2(int, callback_op, cmd, arg);
2818c2ecf20Sopenharmony_ci}
2828c2ecf20Sopenharmony_ci
2838c2ecf20Sopenharmony_cistatic inline int
2848c2ecf20Sopenharmony_ciHYPERVISOR_sched_op(int cmd, void *arg)
2858c2ecf20Sopenharmony_ci{
2868c2ecf20Sopenharmony_ci	return _hypercall2(int, sched_op, cmd, arg);
2878c2ecf20Sopenharmony_ci}
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_cistatic inline long
2908c2ecf20Sopenharmony_ciHYPERVISOR_set_timer_op(u64 timeout)
2918c2ecf20Sopenharmony_ci{
2928c2ecf20Sopenharmony_ci	unsigned long timeout_hi = (unsigned long)(timeout>>32);
2938c2ecf20Sopenharmony_ci	unsigned long timeout_lo = (unsigned long)timeout;
2948c2ecf20Sopenharmony_ci	return _hypercall2(long, set_timer_op, timeout_lo, timeout_hi);
2958c2ecf20Sopenharmony_ci}
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_cistatic inline int
2988c2ecf20Sopenharmony_ciHYPERVISOR_mca(struct xen_mc *mc_op)
2998c2ecf20Sopenharmony_ci{
3008c2ecf20Sopenharmony_ci	mc_op->interface_version = XEN_MCA_INTERFACE_VERSION;
3018c2ecf20Sopenharmony_ci	return _hypercall1(int, mca, mc_op);
3028c2ecf20Sopenharmony_ci}
3038c2ecf20Sopenharmony_ci
3048c2ecf20Sopenharmony_cistatic inline int
3058c2ecf20Sopenharmony_ciHYPERVISOR_platform_op(struct xen_platform_op *op)
3068c2ecf20Sopenharmony_ci{
3078c2ecf20Sopenharmony_ci	op->interface_version = XENPF_INTERFACE_VERSION;
3088c2ecf20Sopenharmony_ci	return _hypercall1(int, platform_op, op);
3098c2ecf20Sopenharmony_ci}
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_cistatic inline int
3128c2ecf20Sopenharmony_ciHYPERVISOR_set_debugreg(int reg, unsigned long value)
3138c2ecf20Sopenharmony_ci{
3148c2ecf20Sopenharmony_ci	return _hypercall2(int, set_debugreg, reg, value);
3158c2ecf20Sopenharmony_ci}
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_cistatic inline unsigned long
3188c2ecf20Sopenharmony_ciHYPERVISOR_get_debugreg(int reg)
3198c2ecf20Sopenharmony_ci{
3208c2ecf20Sopenharmony_ci	return _hypercall1(unsigned long, get_debugreg, reg);
3218c2ecf20Sopenharmony_ci}
3228c2ecf20Sopenharmony_ci
3238c2ecf20Sopenharmony_cistatic inline int
3248c2ecf20Sopenharmony_ciHYPERVISOR_update_descriptor(u64 ma, u64 desc)
3258c2ecf20Sopenharmony_ci{
3268c2ecf20Sopenharmony_ci	if (sizeof(u64) == sizeof(long))
3278c2ecf20Sopenharmony_ci		return _hypercall2(int, update_descriptor, ma, desc);
3288c2ecf20Sopenharmony_ci	return _hypercall4(int, update_descriptor, ma, ma>>32, desc, desc>>32);
3298c2ecf20Sopenharmony_ci}
3308c2ecf20Sopenharmony_ci
3318c2ecf20Sopenharmony_cistatic inline long
3328c2ecf20Sopenharmony_ciHYPERVISOR_memory_op(unsigned int cmd, void *arg)
3338c2ecf20Sopenharmony_ci{
3348c2ecf20Sopenharmony_ci	return _hypercall2(long, memory_op, cmd, arg);
3358c2ecf20Sopenharmony_ci}
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_cistatic inline int
3388c2ecf20Sopenharmony_ciHYPERVISOR_multicall(void *call_list, uint32_t nr_calls)
3398c2ecf20Sopenharmony_ci{
3408c2ecf20Sopenharmony_ci	return _hypercall2(int, multicall, call_list, nr_calls);
3418c2ecf20Sopenharmony_ci}
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_cistatic inline int
3448c2ecf20Sopenharmony_ciHYPERVISOR_update_va_mapping(unsigned long va, pte_t new_val,
3458c2ecf20Sopenharmony_ci			     unsigned long flags)
3468c2ecf20Sopenharmony_ci{
3478c2ecf20Sopenharmony_ci	if (sizeof(new_val) == sizeof(long))
3488c2ecf20Sopenharmony_ci		return _hypercall3(int, update_va_mapping, va,
3498c2ecf20Sopenharmony_ci				   new_val.pte, flags);
3508c2ecf20Sopenharmony_ci	else
3518c2ecf20Sopenharmony_ci		return _hypercall4(int, update_va_mapping, va,
3528c2ecf20Sopenharmony_ci				   new_val.pte, new_val.pte >> 32, flags);
3538c2ecf20Sopenharmony_ci}
3548c2ecf20Sopenharmony_ci
3558c2ecf20Sopenharmony_cistatic inline int
3568c2ecf20Sopenharmony_ciHYPERVISOR_event_channel_op(int cmd, void *arg)
3578c2ecf20Sopenharmony_ci{
3588c2ecf20Sopenharmony_ci	return _hypercall2(int, event_channel_op, cmd, arg);
3598c2ecf20Sopenharmony_ci}
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_cistatic inline int
3628c2ecf20Sopenharmony_ciHYPERVISOR_xen_version(int cmd, void *arg)
3638c2ecf20Sopenharmony_ci{
3648c2ecf20Sopenharmony_ci	return _hypercall2(int, xen_version, cmd, arg);
3658c2ecf20Sopenharmony_ci}
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_cistatic inline int
3688c2ecf20Sopenharmony_ciHYPERVISOR_console_io(int cmd, int count, char *str)
3698c2ecf20Sopenharmony_ci{
3708c2ecf20Sopenharmony_ci	return _hypercall3(int, console_io, cmd, count, str);
3718c2ecf20Sopenharmony_ci}
3728c2ecf20Sopenharmony_ci
3738c2ecf20Sopenharmony_cistatic inline int
3748c2ecf20Sopenharmony_ciHYPERVISOR_physdev_op(int cmd, void *arg)
3758c2ecf20Sopenharmony_ci{
3768c2ecf20Sopenharmony_ci	return _hypercall2(int, physdev_op, cmd, arg);
3778c2ecf20Sopenharmony_ci}
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_cistatic inline int
3808c2ecf20Sopenharmony_ciHYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count)
3818c2ecf20Sopenharmony_ci{
3828c2ecf20Sopenharmony_ci	return _hypercall3(int, grant_table_op, cmd, uop, count);
3838c2ecf20Sopenharmony_ci}
3848c2ecf20Sopenharmony_ci
3858c2ecf20Sopenharmony_cistatic inline int
3868c2ecf20Sopenharmony_ciHYPERVISOR_vm_assist(unsigned int cmd, unsigned int type)
3878c2ecf20Sopenharmony_ci{
3888c2ecf20Sopenharmony_ci	return _hypercall2(int, vm_assist, cmd, type);
3898c2ecf20Sopenharmony_ci}
3908c2ecf20Sopenharmony_ci
3918c2ecf20Sopenharmony_cistatic inline int
3928c2ecf20Sopenharmony_ciHYPERVISOR_vcpu_op(int cmd, int vcpuid, void *extra_args)
3938c2ecf20Sopenharmony_ci{
3948c2ecf20Sopenharmony_ci	return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args);
3958c2ecf20Sopenharmony_ci}
3968c2ecf20Sopenharmony_ci
3978c2ecf20Sopenharmony_ci#ifdef CONFIG_X86_64
3988c2ecf20Sopenharmony_cistatic inline int
3998c2ecf20Sopenharmony_ciHYPERVISOR_set_segment_base(int reg, unsigned long value)
4008c2ecf20Sopenharmony_ci{
4018c2ecf20Sopenharmony_ci	return _hypercall2(int, set_segment_base, reg, value);
4028c2ecf20Sopenharmony_ci}
4038c2ecf20Sopenharmony_ci#endif
4048c2ecf20Sopenharmony_ci
4058c2ecf20Sopenharmony_cistatic inline int
4068c2ecf20Sopenharmony_ciHYPERVISOR_suspend(unsigned long start_info_mfn)
4078c2ecf20Sopenharmony_ci{
4088c2ecf20Sopenharmony_ci	struct sched_shutdown r = { .reason = SHUTDOWN_suspend };
4098c2ecf20Sopenharmony_ci
4108c2ecf20Sopenharmony_ci	/*
4118c2ecf20Sopenharmony_ci	 * For a PV guest the tools require that the start_info mfn be
4128c2ecf20Sopenharmony_ci	 * present in rdx/edx when the hypercall is made. Per the
4138c2ecf20Sopenharmony_ci	 * hypercall calling convention this is the third hypercall
4148c2ecf20Sopenharmony_ci	 * argument, which is start_info_mfn here.
4158c2ecf20Sopenharmony_ci	 */
4168c2ecf20Sopenharmony_ci	return _hypercall3(int, sched_op, SCHEDOP_shutdown, &r, start_info_mfn);
4178c2ecf20Sopenharmony_ci}
4188c2ecf20Sopenharmony_ci
4198c2ecf20Sopenharmony_cistatic inline unsigned long __must_check
4208c2ecf20Sopenharmony_ciHYPERVISOR_hvm_op(int op, void *arg)
4218c2ecf20Sopenharmony_ci{
4228c2ecf20Sopenharmony_ci       return _hypercall2(unsigned long, hvm_op, op, arg);
4238c2ecf20Sopenharmony_ci}
4248c2ecf20Sopenharmony_ci
4258c2ecf20Sopenharmony_cistatic inline int
4268c2ecf20Sopenharmony_ciHYPERVISOR_tmem_op(
4278c2ecf20Sopenharmony_ci	struct tmem_op *op)
4288c2ecf20Sopenharmony_ci{
4298c2ecf20Sopenharmony_ci	return _hypercall1(int, tmem_op, op);
4308c2ecf20Sopenharmony_ci}
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_cistatic inline int
4338c2ecf20Sopenharmony_ciHYPERVISOR_xenpmu_op(unsigned int op, void *arg)
4348c2ecf20Sopenharmony_ci{
4358c2ecf20Sopenharmony_ci	return _hypercall2(int, xenpmu_op, op, arg);
4368c2ecf20Sopenharmony_ci}
4378c2ecf20Sopenharmony_ci
4388c2ecf20Sopenharmony_cistatic inline int
4398c2ecf20Sopenharmony_ciHYPERVISOR_dm_op(
4408c2ecf20Sopenharmony_ci	domid_t dom, unsigned int nr_bufs, struct xen_dm_op_buf *bufs)
4418c2ecf20Sopenharmony_ci{
4428c2ecf20Sopenharmony_ci	int ret;
4438c2ecf20Sopenharmony_ci	__xen_stac();
4448c2ecf20Sopenharmony_ci	ret = _hypercall3(int, dm_op, dom, nr_bufs, bufs);
4458c2ecf20Sopenharmony_ci	__xen_clac();
4468c2ecf20Sopenharmony_ci	return ret;
4478c2ecf20Sopenharmony_ci}
4488c2ecf20Sopenharmony_ci
4498c2ecf20Sopenharmony_cistatic inline void
4508c2ecf20Sopenharmony_ciMULTI_fpu_taskswitch(struct multicall_entry *mcl, int set)
4518c2ecf20Sopenharmony_ci{
4528c2ecf20Sopenharmony_ci	mcl->op = __HYPERVISOR_fpu_taskswitch;
4538c2ecf20Sopenharmony_ci	mcl->args[0] = set;
4548c2ecf20Sopenharmony_ci
4558c2ecf20Sopenharmony_ci	trace_xen_mc_entry(mcl, 1);
4568c2ecf20Sopenharmony_ci}
4578c2ecf20Sopenharmony_ci
4588c2ecf20Sopenharmony_cistatic inline void
4598c2ecf20Sopenharmony_ciMULTI_update_va_mapping(struct multicall_entry *mcl, unsigned long va,
4608c2ecf20Sopenharmony_ci			pte_t new_val, unsigned long flags)
4618c2ecf20Sopenharmony_ci{
4628c2ecf20Sopenharmony_ci	mcl->op = __HYPERVISOR_update_va_mapping;
4638c2ecf20Sopenharmony_ci	mcl->args[0] = va;
4648c2ecf20Sopenharmony_ci	if (sizeof(new_val) == sizeof(long)) {
4658c2ecf20Sopenharmony_ci		mcl->args[1] = new_val.pte;
4668c2ecf20Sopenharmony_ci		mcl->args[2] = flags;
4678c2ecf20Sopenharmony_ci	} else {
4688c2ecf20Sopenharmony_ci		mcl->args[1] = new_val.pte;
4698c2ecf20Sopenharmony_ci		mcl->args[2] = new_val.pte >> 32;
4708c2ecf20Sopenharmony_ci		mcl->args[3] = flags;
4718c2ecf20Sopenharmony_ci	}
4728c2ecf20Sopenharmony_ci
4738c2ecf20Sopenharmony_ci	trace_xen_mc_entry(mcl, sizeof(new_val) == sizeof(long) ? 3 : 4);
4748c2ecf20Sopenharmony_ci}
4758c2ecf20Sopenharmony_ci
4768c2ecf20Sopenharmony_cistatic inline void
4778c2ecf20Sopenharmony_ciMULTI_update_descriptor(struct multicall_entry *mcl, u64 maddr,
4788c2ecf20Sopenharmony_ci			struct desc_struct desc)
4798c2ecf20Sopenharmony_ci{
4808c2ecf20Sopenharmony_ci	mcl->op = __HYPERVISOR_update_descriptor;
4818c2ecf20Sopenharmony_ci	if (sizeof(maddr) == sizeof(long)) {
4828c2ecf20Sopenharmony_ci		mcl->args[0] = maddr;
4838c2ecf20Sopenharmony_ci		mcl->args[1] = *(unsigned long *)&desc;
4848c2ecf20Sopenharmony_ci	} else {
4858c2ecf20Sopenharmony_ci		u32 *p = (u32 *)&desc;
4868c2ecf20Sopenharmony_ci
4878c2ecf20Sopenharmony_ci		mcl->args[0] = maddr;
4888c2ecf20Sopenharmony_ci		mcl->args[1] = maddr >> 32;
4898c2ecf20Sopenharmony_ci		mcl->args[2] = *p++;
4908c2ecf20Sopenharmony_ci		mcl->args[3] = *p;
4918c2ecf20Sopenharmony_ci	}
4928c2ecf20Sopenharmony_ci
4938c2ecf20Sopenharmony_ci	trace_xen_mc_entry(mcl, sizeof(maddr) == sizeof(long) ? 2 : 4);
4948c2ecf20Sopenharmony_ci}
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_cistatic inline void
4978c2ecf20Sopenharmony_ciMULTI_mmu_update(struct multicall_entry *mcl, struct mmu_update *req,
4988c2ecf20Sopenharmony_ci		 int count, int *success_count, domid_t domid)
4998c2ecf20Sopenharmony_ci{
5008c2ecf20Sopenharmony_ci	mcl->op = __HYPERVISOR_mmu_update;
5018c2ecf20Sopenharmony_ci	mcl->args[0] = (unsigned long)req;
5028c2ecf20Sopenharmony_ci	mcl->args[1] = count;
5038c2ecf20Sopenharmony_ci	mcl->args[2] = (unsigned long)success_count;
5048c2ecf20Sopenharmony_ci	mcl->args[3] = domid;
5058c2ecf20Sopenharmony_ci
5068c2ecf20Sopenharmony_ci	trace_xen_mc_entry(mcl, 4);
5078c2ecf20Sopenharmony_ci}
5088c2ecf20Sopenharmony_ci
5098c2ecf20Sopenharmony_cistatic inline void
5108c2ecf20Sopenharmony_ciMULTI_mmuext_op(struct multicall_entry *mcl, struct mmuext_op *op, int count,
5118c2ecf20Sopenharmony_ci		int *success_count, domid_t domid)
5128c2ecf20Sopenharmony_ci{
5138c2ecf20Sopenharmony_ci	mcl->op = __HYPERVISOR_mmuext_op;
5148c2ecf20Sopenharmony_ci	mcl->args[0] = (unsigned long)op;
5158c2ecf20Sopenharmony_ci	mcl->args[1] = count;
5168c2ecf20Sopenharmony_ci	mcl->args[2] = (unsigned long)success_count;
5178c2ecf20Sopenharmony_ci	mcl->args[3] = domid;
5188c2ecf20Sopenharmony_ci
5198c2ecf20Sopenharmony_ci	trace_xen_mc_entry(mcl, 4);
5208c2ecf20Sopenharmony_ci}
5218c2ecf20Sopenharmony_ci
5228c2ecf20Sopenharmony_cistatic inline void
5238c2ecf20Sopenharmony_ciMULTI_stack_switch(struct multicall_entry *mcl,
5248c2ecf20Sopenharmony_ci		   unsigned long ss, unsigned long esp)
5258c2ecf20Sopenharmony_ci{
5268c2ecf20Sopenharmony_ci	mcl->op = __HYPERVISOR_stack_switch;
5278c2ecf20Sopenharmony_ci	mcl->args[0] = ss;
5288c2ecf20Sopenharmony_ci	mcl->args[1] = esp;
5298c2ecf20Sopenharmony_ci
5308c2ecf20Sopenharmony_ci	trace_xen_mc_entry(mcl, 2);
5318c2ecf20Sopenharmony_ci}
5328c2ecf20Sopenharmony_ci
5338c2ecf20Sopenharmony_ci#endif /* _ASM_X86_XEN_HYPERCALL_H */
534