162306a36Sopenharmony_ci/******************************************************************************
262306a36Sopenharmony_ci * hypercall.h
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Linux-specific hypervisor handling.
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Copyright (c) 2002-2004, K A Fraser
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci * This program is free software; you can redistribute it and/or
962306a36Sopenharmony_ci * modify it under the terms of the GNU General Public License version 2
1062306a36Sopenharmony_ci * as published by the Free Software Foundation; or, when distributed
1162306a36Sopenharmony_ci * separately from the Linux kernel or incorporated into other
1262306a36Sopenharmony_ci * software packages, subject to the following license:
1362306a36Sopenharmony_ci *
1462306a36Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy
1562306a36Sopenharmony_ci * of this source file (the "Software"), to deal in the Software without
1662306a36Sopenharmony_ci * restriction, including without limitation the rights to use, copy, modify,
1762306a36Sopenharmony_ci * merge, publish, distribute, sublicense, and/or sell copies of the Software,
1862306a36Sopenharmony_ci * and to permit persons to whom the Software is furnished to do so, subject to
1962306a36Sopenharmony_ci * the following conditions:
2062306a36Sopenharmony_ci *
2162306a36Sopenharmony_ci * The above copyright notice and this permission notice shall be included in
2262306a36Sopenharmony_ci * all copies or substantial portions of the Software.
2362306a36Sopenharmony_ci *
2462306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2562306a36Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2662306a36Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2762306a36Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2862306a36Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2962306a36Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
3062306a36Sopenharmony_ci * IN THE SOFTWARE.
3162306a36Sopenharmony_ci */
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci#ifndef _ASM_X86_XEN_HYPERCALL_H
3462306a36Sopenharmony_ci#define _ASM_X86_XEN_HYPERCALL_H
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci#include <linux/kernel.h>
3762306a36Sopenharmony_ci#include <linux/spinlock.h>
3862306a36Sopenharmony_ci#include <linux/errno.h>
3962306a36Sopenharmony_ci#include <linux/string.h>
4062306a36Sopenharmony_ci#include <linux/types.h>
4162306a36Sopenharmony_ci#include <linux/pgtable.h>
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci#include <trace/events/xen.h>
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci#include <asm/page.h>
4662306a36Sopenharmony_ci#include <asm/smap.h>
4762306a36Sopenharmony_ci#include <asm/nospec-branch.h>
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci#include <xen/interface/xen.h>
5062306a36Sopenharmony_ci#include <xen/interface/sched.h>
5162306a36Sopenharmony_ci#include <xen/interface/physdev.h>
5262306a36Sopenharmony_ci#include <xen/interface/platform.h>
5362306a36Sopenharmony_ci#include <xen/interface/xen-mca.h>
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_cistruct xen_dm_op_buf;
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci/*
5862306a36Sopenharmony_ci * The hypercall asms have to meet several constraints:
5962306a36Sopenharmony_ci * - Work on 32- and 64-bit.
6062306a36Sopenharmony_ci *    The two architectures put their arguments in different sets of
6162306a36Sopenharmony_ci *    registers.
6262306a36Sopenharmony_ci *
6362306a36Sopenharmony_ci * - Work around asm syntax quirks
6462306a36Sopenharmony_ci *    It isn't possible to specify one of the rNN registers in a
6562306a36Sopenharmony_ci *    constraint, so we use explicit register variables to get the
6662306a36Sopenharmony_ci *    args into the right place.
6762306a36Sopenharmony_ci *
6862306a36Sopenharmony_ci * - Mark all registers as potentially clobbered
6962306a36Sopenharmony_ci *    Even unused parameters can be clobbered by the hypervisor, so we
7062306a36Sopenharmony_ci *    need to make sure gcc knows it.
7162306a36Sopenharmony_ci *
7262306a36Sopenharmony_ci * - Avoid compiler bugs.
7362306a36Sopenharmony_ci *    This is the tricky part.  Because x86_32 has such a constrained
7462306a36Sopenharmony_ci *    register set, gcc versions below 4.3 have trouble generating
7562306a36Sopenharmony_ci *    code when all the arg registers and memory are trashed by the
7662306a36Sopenharmony_ci *    asm.  There are syntactically simpler ways of achieving the
7762306a36Sopenharmony_ci *    semantics below, but they cause the compiler to crash.
7862306a36Sopenharmony_ci *
7962306a36Sopenharmony_ci *    The only combination I found which works is:
8062306a36Sopenharmony_ci *     - assign the __argX variables first
8162306a36Sopenharmony_ci *     - list all actually used parameters as "+r" (__argX)
8262306a36Sopenharmony_ci *     - clobber the rest
8362306a36Sopenharmony_ci *
8462306a36Sopenharmony_ci * The result certainly isn't pretty, and it really shows up cpp's
8562306a36Sopenharmony_ci * weakness as a macro language.  Sorry.  (But let's just give thanks
8662306a36Sopenharmony_ci * there aren't more than 5 arguments...)
8762306a36Sopenharmony_ci */
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ciextern struct { char _entry[32]; } hypercall_page[];
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci#define __HYPERCALL		"call hypercall_page+%c[offset]"
9262306a36Sopenharmony_ci#define __HYPERCALL_ENTRY(x)						\
9362306a36Sopenharmony_ci	[offset] "i" (__HYPERVISOR_##x * sizeof(hypercall_page[0]))
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci#ifdef CONFIG_X86_32
9662306a36Sopenharmony_ci#define __HYPERCALL_RETREG	"eax"
9762306a36Sopenharmony_ci#define __HYPERCALL_ARG1REG	"ebx"
9862306a36Sopenharmony_ci#define __HYPERCALL_ARG2REG	"ecx"
9962306a36Sopenharmony_ci#define __HYPERCALL_ARG3REG	"edx"
10062306a36Sopenharmony_ci#define __HYPERCALL_ARG4REG	"esi"
10162306a36Sopenharmony_ci#define __HYPERCALL_ARG5REG	"edi"
10262306a36Sopenharmony_ci#else
10362306a36Sopenharmony_ci#define __HYPERCALL_RETREG	"rax"
10462306a36Sopenharmony_ci#define __HYPERCALL_ARG1REG	"rdi"
10562306a36Sopenharmony_ci#define __HYPERCALL_ARG2REG	"rsi"
10662306a36Sopenharmony_ci#define __HYPERCALL_ARG3REG	"rdx"
10762306a36Sopenharmony_ci#define __HYPERCALL_ARG4REG	"r10"
10862306a36Sopenharmony_ci#define __HYPERCALL_ARG5REG	"r8"
10962306a36Sopenharmony_ci#endif
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci#define __HYPERCALL_DECLS						\
11262306a36Sopenharmony_ci	register unsigned long __res  asm(__HYPERCALL_RETREG);		\
11362306a36Sopenharmony_ci	register unsigned long __arg1 asm(__HYPERCALL_ARG1REG) = __arg1; \
11462306a36Sopenharmony_ci	register unsigned long __arg2 asm(__HYPERCALL_ARG2REG) = __arg2; \
11562306a36Sopenharmony_ci	register unsigned long __arg3 asm(__HYPERCALL_ARG3REG) = __arg3; \
11662306a36Sopenharmony_ci	register unsigned long __arg4 asm(__HYPERCALL_ARG4REG) = __arg4; \
11762306a36Sopenharmony_ci	register unsigned long __arg5 asm(__HYPERCALL_ARG5REG) = __arg5;
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci#define __HYPERCALL_0PARAM	"=r" (__res), ASM_CALL_CONSTRAINT
12062306a36Sopenharmony_ci#define __HYPERCALL_1PARAM	__HYPERCALL_0PARAM, "+r" (__arg1)
12162306a36Sopenharmony_ci#define __HYPERCALL_2PARAM	__HYPERCALL_1PARAM, "+r" (__arg2)
12262306a36Sopenharmony_ci#define __HYPERCALL_3PARAM	__HYPERCALL_2PARAM, "+r" (__arg3)
12362306a36Sopenharmony_ci#define __HYPERCALL_4PARAM	__HYPERCALL_3PARAM, "+r" (__arg4)
12462306a36Sopenharmony_ci#define __HYPERCALL_5PARAM	__HYPERCALL_4PARAM, "+r" (__arg5)
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci#define __HYPERCALL_0ARG()
12762306a36Sopenharmony_ci#define __HYPERCALL_1ARG(a1)						\
12862306a36Sopenharmony_ci	__HYPERCALL_0ARG()		__arg1 = (unsigned long)(a1);
12962306a36Sopenharmony_ci#define __HYPERCALL_2ARG(a1,a2)						\
13062306a36Sopenharmony_ci	__HYPERCALL_1ARG(a1)		__arg2 = (unsigned long)(a2);
13162306a36Sopenharmony_ci#define __HYPERCALL_3ARG(a1,a2,a3)					\
13262306a36Sopenharmony_ci	__HYPERCALL_2ARG(a1,a2)		__arg3 = (unsigned long)(a3);
13362306a36Sopenharmony_ci#define __HYPERCALL_4ARG(a1,a2,a3,a4)					\
13462306a36Sopenharmony_ci	__HYPERCALL_3ARG(a1,a2,a3)	__arg4 = (unsigned long)(a4);
13562306a36Sopenharmony_ci#define __HYPERCALL_5ARG(a1,a2,a3,a4,a5)				\
13662306a36Sopenharmony_ci	__HYPERCALL_4ARG(a1,a2,a3,a4)	__arg5 = (unsigned long)(a5);
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci#define __HYPERCALL_CLOBBER5	"memory"
13962306a36Sopenharmony_ci#define __HYPERCALL_CLOBBER4	__HYPERCALL_CLOBBER5, __HYPERCALL_ARG5REG
14062306a36Sopenharmony_ci#define __HYPERCALL_CLOBBER3	__HYPERCALL_CLOBBER4, __HYPERCALL_ARG4REG
14162306a36Sopenharmony_ci#define __HYPERCALL_CLOBBER2	__HYPERCALL_CLOBBER3, __HYPERCALL_ARG3REG
14262306a36Sopenharmony_ci#define __HYPERCALL_CLOBBER1	__HYPERCALL_CLOBBER2, __HYPERCALL_ARG2REG
14362306a36Sopenharmony_ci#define __HYPERCALL_CLOBBER0	__HYPERCALL_CLOBBER1, __HYPERCALL_ARG1REG
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci#define _hypercall0(type, name)						\
14662306a36Sopenharmony_ci({									\
14762306a36Sopenharmony_ci	__HYPERCALL_DECLS;						\
14862306a36Sopenharmony_ci	__HYPERCALL_0ARG();						\
14962306a36Sopenharmony_ci	asm volatile (__HYPERCALL					\
15062306a36Sopenharmony_ci		      : __HYPERCALL_0PARAM				\
15162306a36Sopenharmony_ci		      : __HYPERCALL_ENTRY(name)				\
15262306a36Sopenharmony_ci		      : __HYPERCALL_CLOBBER0);				\
15362306a36Sopenharmony_ci	(type)__res;							\
15462306a36Sopenharmony_ci})
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ci#define _hypercall1(type, name, a1)					\
15762306a36Sopenharmony_ci({									\
15862306a36Sopenharmony_ci	__HYPERCALL_DECLS;						\
15962306a36Sopenharmony_ci	__HYPERCALL_1ARG(a1);						\
16062306a36Sopenharmony_ci	asm volatile (__HYPERCALL					\
16162306a36Sopenharmony_ci		      : __HYPERCALL_1PARAM				\
16262306a36Sopenharmony_ci		      : __HYPERCALL_ENTRY(name)				\
16362306a36Sopenharmony_ci		      : __HYPERCALL_CLOBBER1);				\
16462306a36Sopenharmony_ci	(type)__res;							\
16562306a36Sopenharmony_ci})
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci#define _hypercall2(type, name, a1, a2)					\
16862306a36Sopenharmony_ci({									\
16962306a36Sopenharmony_ci	__HYPERCALL_DECLS;						\
17062306a36Sopenharmony_ci	__HYPERCALL_2ARG(a1, a2);					\
17162306a36Sopenharmony_ci	asm volatile (__HYPERCALL					\
17262306a36Sopenharmony_ci		      : __HYPERCALL_2PARAM				\
17362306a36Sopenharmony_ci		      : __HYPERCALL_ENTRY(name)				\
17462306a36Sopenharmony_ci		      : __HYPERCALL_CLOBBER2);				\
17562306a36Sopenharmony_ci	(type)__res;							\
17662306a36Sopenharmony_ci})
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ci#define _hypercall3(type, name, a1, a2, a3)				\
17962306a36Sopenharmony_ci({									\
18062306a36Sopenharmony_ci	__HYPERCALL_DECLS;						\
18162306a36Sopenharmony_ci	__HYPERCALL_3ARG(a1, a2, a3);					\
18262306a36Sopenharmony_ci	asm volatile (__HYPERCALL					\
18362306a36Sopenharmony_ci		      : __HYPERCALL_3PARAM				\
18462306a36Sopenharmony_ci		      : __HYPERCALL_ENTRY(name)				\
18562306a36Sopenharmony_ci		      : __HYPERCALL_CLOBBER3);				\
18662306a36Sopenharmony_ci	(type)__res;							\
18762306a36Sopenharmony_ci})
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_ci#define _hypercall4(type, name, a1, a2, a3, a4)				\
19062306a36Sopenharmony_ci({									\
19162306a36Sopenharmony_ci	__HYPERCALL_DECLS;						\
19262306a36Sopenharmony_ci	__HYPERCALL_4ARG(a1, a2, a3, a4);				\
19362306a36Sopenharmony_ci	asm volatile (__HYPERCALL					\
19462306a36Sopenharmony_ci		      : __HYPERCALL_4PARAM				\
19562306a36Sopenharmony_ci		      : __HYPERCALL_ENTRY(name)				\
19662306a36Sopenharmony_ci		      : __HYPERCALL_CLOBBER4);				\
19762306a36Sopenharmony_ci	(type)__res;							\
19862306a36Sopenharmony_ci})
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_cistatic inline long
20162306a36Sopenharmony_cixen_single_call(unsigned int call,
20262306a36Sopenharmony_ci		unsigned long a1, unsigned long a2,
20362306a36Sopenharmony_ci		unsigned long a3, unsigned long a4,
20462306a36Sopenharmony_ci		unsigned long a5)
20562306a36Sopenharmony_ci{
20662306a36Sopenharmony_ci	__HYPERCALL_DECLS;
20762306a36Sopenharmony_ci	__HYPERCALL_5ARG(a1, a2, a3, a4, a5);
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci	if (call >= PAGE_SIZE / sizeof(hypercall_page[0]))
21062306a36Sopenharmony_ci		return -EINVAL;
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci	asm volatile(CALL_NOSPEC
21362306a36Sopenharmony_ci		     : __HYPERCALL_5PARAM
21462306a36Sopenharmony_ci		     : [thunk_target] "a" (&hypercall_page[call])
21562306a36Sopenharmony_ci		     : __HYPERCALL_CLOBBER5);
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_ci	return (long)__res;
21862306a36Sopenharmony_ci}
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_cistatic __always_inline void __xen_stac(void)
22162306a36Sopenharmony_ci{
22262306a36Sopenharmony_ci	/*
22362306a36Sopenharmony_ci	 * Suppress objtool seeing the STAC/CLAC and getting confused about it
22462306a36Sopenharmony_ci	 * calling random code with AC=1.
22562306a36Sopenharmony_ci	 */
22662306a36Sopenharmony_ci	asm volatile(ANNOTATE_IGNORE_ALTERNATIVE
22762306a36Sopenharmony_ci		     ASM_STAC ::: "memory", "flags");
22862306a36Sopenharmony_ci}
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_cistatic __always_inline void __xen_clac(void)
23162306a36Sopenharmony_ci{
23262306a36Sopenharmony_ci	asm volatile(ANNOTATE_IGNORE_ALTERNATIVE
23362306a36Sopenharmony_ci		     ASM_CLAC ::: "memory", "flags");
23462306a36Sopenharmony_ci}
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_cistatic inline long
23762306a36Sopenharmony_ciprivcmd_call(unsigned int call,
23862306a36Sopenharmony_ci	     unsigned long a1, unsigned long a2,
23962306a36Sopenharmony_ci	     unsigned long a3, unsigned long a4,
24062306a36Sopenharmony_ci	     unsigned long a5)
24162306a36Sopenharmony_ci{
24262306a36Sopenharmony_ci	long res;
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci	__xen_stac();
24562306a36Sopenharmony_ci	res = xen_single_call(call, a1, a2, a3, a4, a5);
24662306a36Sopenharmony_ci	__xen_clac();
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_ci	return res;
24962306a36Sopenharmony_ci}
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_ci#ifdef CONFIG_XEN_PV
25262306a36Sopenharmony_cistatic inline int
25362306a36Sopenharmony_ciHYPERVISOR_set_trap_table(struct trap_info *table)
25462306a36Sopenharmony_ci{
25562306a36Sopenharmony_ci	return _hypercall1(int, set_trap_table, table);
25662306a36Sopenharmony_ci}
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_cistatic inline int
25962306a36Sopenharmony_ciHYPERVISOR_mmu_update(struct mmu_update *req, int count,
26062306a36Sopenharmony_ci		      int *success_count, domid_t domid)
26162306a36Sopenharmony_ci{
26262306a36Sopenharmony_ci	return _hypercall4(int, mmu_update, req, count, success_count, domid);
26362306a36Sopenharmony_ci}
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_cistatic inline int
26662306a36Sopenharmony_ciHYPERVISOR_mmuext_op(struct mmuext_op *op, int count,
26762306a36Sopenharmony_ci		     int *success_count, domid_t domid)
26862306a36Sopenharmony_ci{
26962306a36Sopenharmony_ci	return _hypercall4(int, mmuext_op, op, count, success_count, domid);
27062306a36Sopenharmony_ci}
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_cistatic inline int
27362306a36Sopenharmony_ciHYPERVISOR_set_gdt(unsigned long *frame_list, int entries)
27462306a36Sopenharmony_ci{
27562306a36Sopenharmony_ci	return _hypercall2(int, set_gdt, frame_list, entries);
27662306a36Sopenharmony_ci}
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_cistatic inline int
27962306a36Sopenharmony_ciHYPERVISOR_callback_op(int cmd, void *arg)
28062306a36Sopenharmony_ci{
28162306a36Sopenharmony_ci	return _hypercall2(int, callback_op, cmd, arg);
28262306a36Sopenharmony_ci}
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_cistatic __always_inline int
28562306a36Sopenharmony_ciHYPERVISOR_set_debugreg(int reg, unsigned long value)
28662306a36Sopenharmony_ci{
28762306a36Sopenharmony_ci	return _hypercall2(int, set_debugreg, reg, value);
28862306a36Sopenharmony_ci}
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_cistatic __always_inline unsigned long
29162306a36Sopenharmony_ciHYPERVISOR_get_debugreg(int reg)
29262306a36Sopenharmony_ci{
29362306a36Sopenharmony_ci	return _hypercall1(unsigned long, get_debugreg, reg);
29462306a36Sopenharmony_ci}
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_cistatic inline int
29762306a36Sopenharmony_ciHYPERVISOR_update_descriptor(u64 ma, u64 desc)
29862306a36Sopenharmony_ci{
29962306a36Sopenharmony_ci	return _hypercall2(int, update_descriptor, ma, desc);
30062306a36Sopenharmony_ci}
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_cistatic inline int
30362306a36Sopenharmony_ciHYPERVISOR_update_va_mapping(unsigned long va, pte_t new_val,
30462306a36Sopenharmony_ci			     unsigned long flags)
30562306a36Sopenharmony_ci{
30662306a36Sopenharmony_ci	return _hypercall3(int, update_va_mapping, va, new_val.pte, flags);
30762306a36Sopenharmony_ci}
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_cistatic inline int
31062306a36Sopenharmony_ciHYPERVISOR_set_segment_base(int reg, unsigned long value)
31162306a36Sopenharmony_ci{
31262306a36Sopenharmony_ci	return _hypercall2(int, set_segment_base, reg, value);
31362306a36Sopenharmony_ci}
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_cistatic inline void
31662306a36Sopenharmony_ciMULTI_fpu_taskswitch(struct multicall_entry *mcl, int set)
31762306a36Sopenharmony_ci{
31862306a36Sopenharmony_ci	mcl->op = __HYPERVISOR_fpu_taskswitch;
31962306a36Sopenharmony_ci	mcl->args[0] = set;
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_ci	trace_xen_mc_entry(mcl, 1);
32262306a36Sopenharmony_ci}
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_cistatic inline void
32562306a36Sopenharmony_ciMULTI_update_va_mapping(struct multicall_entry *mcl, unsigned long va,
32662306a36Sopenharmony_ci			pte_t new_val, unsigned long flags)
32762306a36Sopenharmony_ci{
32862306a36Sopenharmony_ci	mcl->op = __HYPERVISOR_update_va_mapping;
32962306a36Sopenharmony_ci	mcl->args[0] = va;
33062306a36Sopenharmony_ci	mcl->args[1] = new_val.pte;
33162306a36Sopenharmony_ci	mcl->args[2] = flags;
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_ci	trace_xen_mc_entry(mcl, 3);
33462306a36Sopenharmony_ci}
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_cistatic inline void
33762306a36Sopenharmony_ciMULTI_update_descriptor(struct multicall_entry *mcl, u64 maddr,
33862306a36Sopenharmony_ci			struct desc_struct desc)
33962306a36Sopenharmony_ci{
34062306a36Sopenharmony_ci	mcl->op = __HYPERVISOR_update_descriptor;
34162306a36Sopenharmony_ci	mcl->args[0] = maddr;
34262306a36Sopenharmony_ci	mcl->args[1] = *(unsigned long *)&desc;
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_ci	trace_xen_mc_entry(mcl, 2);
34562306a36Sopenharmony_ci}
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_cistatic inline void
34862306a36Sopenharmony_ciMULTI_mmu_update(struct multicall_entry *mcl, struct mmu_update *req,
34962306a36Sopenharmony_ci		 int count, int *success_count, domid_t domid)
35062306a36Sopenharmony_ci{
35162306a36Sopenharmony_ci	mcl->op = __HYPERVISOR_mmu_update;
35262306a36Sopenharmony_ci	mcl->args[0] = (unsigned long)req;
35362306a36Sopenharmony_ci	mcl->args[1] = count;
35462306a36Sopenharmony_ci	mcl->args[2] = (unsigned long)success_count;
35562306a36Sopenharmony_ci	mcl->args[3] = domid;
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_ci	trace_xen_mc_entry(mcl, 4);
35862306a36Sopenharmony_ci}
35962306a36Sopenharmony_ci
36062306a36Sopenharmony_cistatic inline void
36162306a36Sopenharmony_ciMULTI_mmuext_op(struct multicall_entry *mcl, struct mmuext_op *op, int count,
36262306a36Sopenharmony_ci		int *success_count, domid_t domid)
36362306a36Sopenharmony_ci{
36462306a36Sopenharmony_ci	mcl->op = __HYPERVISOR_mmuext_op;
36562306a36Sopenharmony_ci	mcl->args[0] = (unsigned long)op;
36662306a36Sopenharmony_ci	mcl->args[1] = count;
36762306a36Sopenharmony_ci	mcl->args[2] = (unsigned long)success_count;
36862306a36Sopenharmony_ci	mcl->args[3] = domid;
36962306a36Sopenharmony_ci
37062306a36Sopenharmony_ci	trace_xen_mc_entry(mcl, 4);
37162306a36Sopenharmony_ci}
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_cistatic inline void
37462306a36Sopenharmony_ciMULTI_stack_switch(struct multicall_entry *mcl,
37562306a36Sopenharmony_ci		   unsigned long ss, unsigned long esp)
37662306a36Sopenharmony_ci{
37762306a36Sopenharmony_ci	mcl->op = __HYPERVISOR_stack_switch;
37862306a36Sopenharmony_ci	mcl->args[0] = ss;
37962306a36Sopenharmony_ci	mcl->args[1] = esp;
38062306a36Sopenharmony_ci
38162306a36Sopenharmony_ci	trace_xen_mc_entry(mcl, 2);
38262306a36Sopenharmony_ci}
38362306a36Sopenharmony_ci#endif
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_cistatic __always_inline int
38662306a36Sopenharmony_ciHYPERVISOR_sched_op(int cmd, void *arg)
38762306a36Sopenharmony_ci{
38862306a36Sopenharmony_ci	return _hypercall2(int, sched_op, cmd, arg);
38962306a36Sopenharmony_ci}
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_cistatic inline long
39262306a36Sopenharmony_ciHYPERVISOR_set_timer_op(u64 timeout)
39362306a36Sopenharmony_ci{
39462306a36Sopenharmony_ci	unsigned long timeout_hi = (unsigned long)(timeout>>32);
39562306a36Sopenharmony_ci	unsigned long timeout_lo = (unsigned long)timeout;
39662306a36Sopenharmony_ci	return _hypercall2(long, set_timer_op, timeout_lo, timeout_hi);
39762306a36Sopenharmony_ci}
39862306a36Sopenharmony_ci
39962306a36Sopenharmony_cistatic inline int
40062306a36Sopenharmony_ciHYPERVISOR_mca(struct xen_mc *mc_op)
40162306a36Sopenharmony_ci{
40262306a36Sopenharmony_ci	mc_op->interface_version = XEN_MCA_INTERFACE_VERSION;
40362306a36Sopenharmony_ci	return _hypercall1(int, mca, mc_op);
40462306a36Sopenharmony_ci}
40562306a36Sopenharmony_ci
40662306a36Sopenharmony_cistatic inline int
40762306a36Sopenharmony_ciHYPERVISOR_platform_op(struct xen_platform_op *op)
40862306a36Sopenharmony_ci{
40962306a36Sopenharmony_ci	op->interface_version = XENPF_INTERFACE_VERSION;
41062306a36Sopenharmony_ci	return _hypercall1(int, platform_op, op);
41162306a36Sopenharmony_ci}
41262306a36Sopenharmony_ci
41362306a36Sopenharmony_cistatic inline long
41462306a36Sopenharmony_ciHYPERVISOR_memory_op(unsigned int cmd, void *arg)
41562306a36Sopenharmony_ci{
41662306a36Sopenharmony_ci	return _hypercall2(long, memory_op, cmd, arg);
41762306a36Sopenharmony_ci}
41862306a36Sopenharmony_ci
41962306a36Sopenharmony_cistatic inline int
42062306a36Sopenharmony_ciHYPERVISOR_multicall(void *call_list, uint32_t nr_calls)
42162306a36Sopenharmony_ci{
42262306a36Sopenharmony_ci	return _hypercall2(int, multicall, call_list, nr_calls);
42362306a36Sopenharmony_ci}
42462306a36Sopenharmony_ci
42562306a36Sopenharmony_cistatic inline int
42662306a36Sopenharmony_ciHYPERVISOR_event_channel_op(int cmd, void *arg)
42762306a36Sopenharmony_ci{
42862306a36Sopenharmony_ci	return _hypercall2(int, event_channel_op, cmd, arg);
42962306a36Sopenharmony_ci}
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_cistatic __always_inline int
43262306a36Sopenharmony_ciHYPERVISOR_xen_version(int cmd, void *arg)
43362306a36Sopenharmony_ci{
43462306a36Sopenharmony_ci	return _hypercall2(int, xen_version, cmd, arg);
43562306a36Sopenharmony_ci}
43662306a36Sopenharmony_ci
43762306a36Sopenharmony_cistatic inline int
43862306a36Sopenharmony_ciHYPERVISOR_console_io(int cmd, int count, char *str)
43962306a36Sopenharmony_ci{
44062306a36Sopenharmony_ci	return _hypercall3(int, console_io, cmd, count, str);
44162306a36Sopenharmony_ci}
44262306a36Sopenharmony_ci
44362306a36Sopenharmony_cistatic inline int
44462306a36Sopenharmony_ciHYPERVISOR_physdev_op(int cmd, void *arg)
44562306a36Sopenharmony_ci{
44662306a36Sopenharmony_ci	return _hypercall2(int, physdev_op, cmd, arg);
44762306a36Sopenharmony_ci}
44862306a36Sopenharmony_ci
44962306a36Sopenharmony_cistatic inline int
45062306a36Sopenharmony_ciHYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count)
45162306a36Sopenharmony_ci{
45262306a36Sopenharmony_ci	return _hypercall3(int, grant_table_op, cmd, uop, count);
45362306a36Sopenharmony_ci}
45462306a36Sopenharmony_ci
45562306a36Sopenharmony_cistatic inline int
45662306a36Sopenharmony_ciHYPERVISOR_vm_assist(unsigned int cmd, unsigned int type)
45762306a36Sopenharmony_ci{
45862306a36Sopenharmony_ci	return _hypercall2(int, vm_assist, cmd, type);
45962306a36Sopenharmony_ci}
46062306a36Sopenharmony_ci
46162306a36Sopenharmony_cistatic inline int
46262306a36Sopenharmony_ciHYPERVISOR_vcpu_op(int cmd, int vcpuid, void *extra_args)
46362306a36Sopenharmony_ci{
46462306a36Sopenharmony_ci	return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args);
46562306a36Sopenharmony_ci}
46662306a36Sopenharmony_ci
46762306a36Sopenharmony_cistatic inline int
46862306a36Sopenharmony_ciHYPERVISOR_suspend(unsigned long start_info_mfn)
46962306a36Sopenharmony_ci{
47062306a36Sopenharmony_ci	struct sched_shutdown r = { .reason = SHUTDOWN_suspend };
47162306a36Sopenharmony_ci
47262306a36Sopenharmony_ci	/*
47362306a36Sopenharmony_ci	 * For a PV guest the tools require that the start_info mfn be
47462306a36Sopenharmony_ci	 * present in rdx/edx when the hypercall is made. Per the
47562306a36Sopenharmony_ci	 * hypercall calling convention this is the third hypercall
47662306a36Sopenharmony_ci	 * argument, which is start_info_mfn here.
47762306a36Sopenharmony_ci	 */
47862306a36Sopenharmony_ci	return _hypercall3(int, sched_op, SCHEDOP_shutdown, &r, start_info_mfn);
47962306a36Sopenharmony_ci}
48062306a36Sopenharmony_ci
48162306a36Sopenharmony_cistatic inline unsigned long __must_check
48262306a36Sopenharmony_ciHYPERVISOR_hvm_op(int op, void *arg)
48362306a36Sopenharmony_ci{
48462306a36Sopenharmony_ci       return _hypercall2(unsigned long, hvm_op, op, arg);
48562306a36Sopenharmony_ci}
48662306a36Sopenharmony_ci
48762306a36Sopenharmony_cistatic inline int
48862306a36Sopenharmony_ciHYPERVISOR_xenpmu_op(unsigned int op, void *arg)
48962306a36Sopenharmony_ci{
49062306a36Sopenharmony_ci	return _hypercall2(int, xenpmu_op, op, arg);
49162306a36Sopenharmony_ci}
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_cistatic inline int
49462306a36Sopenharmony_ciHYPERVISOR_dm_op(
49562306a36Sopenharmony_ci	domid_t dom, unsigned int nr_bufs, struct xen_dm_op_buf *bufs)
49662306a36Sopenharmony_ci{
49762306a36Sopenharmony_ci	int ret;
49862306a36Sopenharmony_ci	__xen_stac();
49962306a36Sopenharmony_ci	ret = _hypercall3(int, dm_op, dom, nr_bufs, bufs);
50062306a36Sopenharmony_ci	__xen_clac();
50162306a36Sopenharmony_ci	return ret;
50262306a36Sopenharmony_ci}
50362306a36Sopenharmony_ci
50462306a36Sopenharmony_ci#endif /* _ASM_X86_XEN_HYPERCALL_H */
505