162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci#ifndef _ASM_X86_XEN_INTERFACE_64_H
362306a36Sopenharmony_ci#define _ASM_X86_XEN_INTERFACE_64_H
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci/*
662306a36Sopenharmony_ci * 64-bit segment selectors
762306a36Sopenharmony_ci * These flat segments are in the Xen-private section of every GDT. Since these
862306a36Sopenharmony_ci * are also present in the initial GDT, many OSes will be able to avoid
962306a36Sopenharmony_ci * installing their own GDT.
1062306a36Sopenharmony_ci */
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#define FLAT_RING3_CS32 0xe023  /* GDT index 260 */
1362306a36Sopenharmony_ci#define FLAT_RING3_CS64 0xe033  /* GDT index 261 */
1462306a36Sopenharmony_ci#define FLAT_RING3_DS32 0xe02b  /* GDT index 262 */
1562306a36Sopenharmony_ci#define FLAT_RING3_DS64 0x0000  /* NULL selector */
1662306a36Sopenharmony_ci#define FLAT_RING3_SS32 0xe02b  /* GDT index 262 */
1762306a36Sopenharmony_ci#define FLAT_RING3_SS64 0xe02b  /* GDT index 262 */
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci#define FLAT_KERNEL_DS64 FLAT_RING3_DS64
2062306a36Sopenharmony_ci#define FLAT_KERNEL_DS32 FLAT_RING3_DS32
2162306a36Sopenharmony_ci#define FLAT_KERNEL_DS   FLAT_KERNEL_DS64
2262306a36Sopenharmony_ci#define FLAT_KERNEL_CS64 FLAT_RING3_CS64
2362306a36Sopenharmony_ci#define FLAT_KERNEL_CS32 FLAT_RING3_CS32
2462306a36Sopenharmony_ci#define FLAT_KERNEL_CS   FLAT_KERNEL_CS64
2562306a36Sopenharmony_ci#define FLAT_KERNEL_SS64 FLAT_RING3_SS64
2662306a36Sopenharmony_ci#define FLAT_KERNEL_SS32 FLAT_RING3_SS32
2762306a36Sopenharmony_ci#define FLAT_KERNEL_SS   FLAT_KERNEL_SS64
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci#define FLAT_USER_DS64 FLAT_RING3_DS64
3062306a36Sopenharmony_ci#define FLAT_USER_DS32 FLAT_RING3_DS32
3162306a36Sopenharmony_ci#define FLAT_USER_DS   FLAT_USER_DS64
3262306a36Sopenharmony_ci#define FLAT_USER_CS64 FLAT_RING3_CS64
3362306a36Sopenharmony_ci#define FLAT_USER_CS32 FLAT_RING3_CS32
3462306a36Sopenharmony_ci#define FLAT_USER_CS   FLAT_USER_CS64
3562306a36Sopenharmony_ci#define FLAT_USER_SS64 FLAT_RING3_SS64
3662306a36Sopenharmony_ci#define FLAT_USER_SS32 FLAT_RING3_SS32
3762306a36Sopenharmony_ci#define FLAT_USER_SS   FLAT_USER_SS64
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci#define __HYPERVISOR_VIRT_START 0xFFFF800000000000
4062306a36Sopenharmony_ci#define __HYPERVISOR_VIRT_END   0xFFFF880000000000
4162306a36Sopenharmony_ci#define __MACH2PHYS_VIRT_START  0xFFFF800000000000
4262306a36Sopenharmony_ci#define __MACH2PHYS_VIRT_END    0xFFFF804000000000
4362306a36Sopenharmony_ci#define __MACH2PHYS_SHIFT       3
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci/*
4662306a36Sopenharmony_ci * int HYPERVISOR_set_segment_base(unsigned int which, unsigned long base)
4762306a36Sopenharmony_ci *  @which == SEGBASE_*  ;  @base == 64-bit base address
4862306a36Sopenharmony_ci * Returns 0 on success.
4962306a36Sopenharmony_ci */
5062306a36Sopenharmony_ci#define SEGBASE_FS          0
5162306a36Sopenharmony_ci#define SEGBASE_GS_USER     1
5262306a36Sopenharmony_ci#define SEGBASE_GS_KERNEL   2
5362306a36Sopenharmony_ci#define SEGBASE_GS_USER_SEL 3 /* Set user %gs specified in base[15:0] */
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci/*
5662306a36Sopenharmony_ci * int HYPERVISOR_iret(void)
5762306a36Sopenharmony_ci * All arguments are on the kernel stack, in the following format.
5862306a36Sopenharmony_ci * Never returns if successful. Current kernel context is lost.
5962306a36Sopenharmony_ci * The saved CS is mapped as follows:
6062306a36Sopenharmony_ci *   RING0 -> RING3 kernel mode.
6162306a36Sopenharmony_ci *   RING1 -> RING3 kernel mode.
6262306a36Sopenharmony_ci *   RING2 -> RING3 kernel mode.
6362306a36Sopenharmony_ci *   RING3 -> RING3 user mode.
6462306a36Sopenharmony_ci * However RING0 indicates that the guest kernel should return to iteself
6562306a36Sopenharmony_ci * directly with
6662306a36Sopenharmony_ci *      orb   $3,1*8(%rsp)
6762306a36Sopenharmony_ci *      iretq
6862306a36Sopenharmony_ci * If flags contains VGCF_in_syscall:
6962306a36Sopenharmony_ci *   Restore RAX, RIP, RFLAGS, RSP.
7062306a36Sopenharmony_ci *   Discard R11, RCX, CS, SS.
7162306a36Sopenharmony_ci * Otherwise:
7262306a36Sopenharmony_ci *   Restore RAX, R11, RCX, CS:RIP, RFLAGS, SS:RSP.
7362306a36Sopenharmony_ci * All other registers are saved on hypercall entry and restored to user.
7462306a36Sopenharmony_ci */
7562306a36Sopenharmony_ci/* Guest exited in SYSCALL context? Return to guest with SYSRET? */
7662306a36Sopenharmony_ci#define _VGCF_in_syscall 8
7762306a36Sopenharmony_ci#define VGCF_in_syscall  (1<<_VGCF_in_syscall)
7862306a36Sopenharmony_ci#define VGCF_IN_SYSCALL  VGCF_in_syscall
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci#ifndef __ASSEMBLY__
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_cistruct iret_context {
8362306a36Sopenharmony_ci    /* Top of stack (%rsp at point of hypercall). */
8462306a36Sopenharmony_ci    uint64_t rax, r11, rcx, flags, rip, cs, rflags, rsp, ss;
8562306a36Sopenharmony_ci    /* Bottom of iret stack frame. */
8662306a36Sopenharmony_ci};
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
8962306a36Sopenharmony_ci/* Anonymous union includes both 32- and 64-bit names (e.g., eax/rax). */
9062306a36Sopenharmony_ci#define __DECL_REG(name) union { \
9162306a36Sopenharmony_ci    uint64_t r ## name, e ## name; \
9262306a36Sopenharmony_ci    uint32_t _e ## name; \
9362306a36Sopenharmony_ci}
9462306a36Sopenharmony_ci#else
9562306a36Sopenharmony_ci/* Non-gcc sources must always use the proper 64-bit name (e.g., rax). */
9662306a36Sopenharmony_ci#define __DECL_REG(name) uint64_t r ## name
9762306a36Sopenharmony_ci#endif
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_cistruct cpu_user_regs {
10062306a36Sopenharmony_ci    uint64_t r15;
10162306a36Sopenharmony_ci    uint64_t r14;
10262306a36Sopenharmony_ci    uint64_t r13;
10362306a36Sopenharmony_ci    uint64_t r12;
10462306a36Sopenharmony_ci    __DECL_REG(bp);
10562306a36Sopenharmony_ci    __DECL_REG(bx);
10662306a36Sopenharmony_ci    uint64_t r11;
10762306a36Sopenharmony_ci    uint64_t r10;
10862306a36Sopenharmony_ci    uint64_t r9;
10962306a36Sopenharmony_ci    uint64_t r8;
11062306a36Sopenharmony_ci    __DECL_REG(ax);
11162306a36Sopenharmony_ci    __DECL_REG(cx);
11262306a36Sopenharmony_ci    __DECL_REG(dx);
11362306a36Sopenharmony_ci    __DECL_REG(si);
11462306a36Sopenharmony_ci    __DECL_REG(di);
11562306a36Sopenharmony_ci    uint32_t error_code;    /* private */
11662306a36Sopenharmony_ci    uint32_t entry_vector;  /* private */
11762306a36Sopenharmony_ci    __DECL_REG(ip);
11862306a36Sopenharmony_ci    uint16_t cs, _pad0[1];
11962306a36Sopenharmony_ci    uint8_t  saved_upcall_mask;
12062306a36Sopenharmony_ci    uint8_t  _pad1[3];
12162306a36Sopenharmony_ci    __DECL_REG(flags);      /* rflags.IF == !saved_upcall_mask */
12262306a36Sopenharmony_ci    __DECL_REG(sp);
12362306a36Sopenharmony_ci    uint16_t ss, _pad2[3];
12462306a36Sopenharmony_ci    uint16_t es, _pad3[3];
12562306a36Sopenharmony_ci    uint16_t ds, _pad4[3];
12662306a36Sopenharmony_ci    uint16_t fs, _pad5[3]; /* Non-zero => takes precedence over fs_base.     */
12762306a36Sopenharmony_ci    uint16_t gs, _pad6[3]; /* Non-zero => takes precedence over gs_base_usr. */
12862306a36Sopenharmony_ci};
12962306a36Sopenharmony_ciDEFINE_GUEST_HANDLE_STRUCT(cpu_user_regs);
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci#undef __DECL_REG
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci#define xen_pfn_to_cr3(pfn) ((unsigned long)(pfn) << 12)
13462306a36Sopenharmony_ci#define xen_cr3_to_pfn(cr3) ((unsigned long)(cr3) >> 12)
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_cistruct arch_vcpu_info {
13762306a36Sopenharmony_ci    unsigned long cr2;
13862306a36Sopenharmony_ci    unsigned long pad; /* sizeof(vcpu_info_t) == 64 */
13962306a36Sopenharmony_ci};
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_citypedef unsigned long xen_callback_t;
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci#define XEN_CALLBACK(__cs, __rip)				\
14462306a36Sopenharmony_ci	((unsigned long)(__rip))
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci#endif /* !__ASSEMBLY__ */
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci#endif /* _ASM_X86_XEN_INTERFACE_64_H */
150