xref: /openbmc/qemu/include/hw/xen/interface/arch-x86/xen-x86_64.h (revision 3e34860a3a03f969ad0720ec9c12ea10e88738a6)
1*8ac98aedSDavid Woodhouse /* SPDX-License-Identifier: MIT */
250c88402SJoao Martins /******************************************************************************
350c88402SJoao Martins  * xen-x86_64.h
450c88402SJoao Martins  *
550c88402SJoao Martins  * Guest OS interface to x86 64-bit Xen.
650c88402SJoao Martins  *
750c88402SJoao Martins  * Copyright (c) 2004-2006, K A Fraser
850c88402SJoao Martins  */
950c88402SJoao Martins 
1050c88402SJoao Martins #ifndef __XEN_PUBLIC_ARCH_X86_XEN_X86_64_H__
1150c88402SJoao Martins #define __XEN_PUBLIC_ARCH_X86_XEN_X86_64_H__
1250c88402SJoao Martins 
1350c88402SJoao Martins /*
1450c88402SJoao Martins  * Hypercall interface:
1550c88402SJoao Martins  *  Input:  %rdi, %rsi, %rdx, %r10, %r8, %r9 (arguments 1-6)
1650c88402SJoao Martins  *  Output: %rax
1750c88402SJoao Martins  * Access is via hypercall page (set up by guest loader or via a Xen MSR):
1850c88402SJoao Martins  *  call hypercall_page + hypercall-number * 32
1950c88402SJoao Martins  * Clobbered: argument registers (e.g., 2-arg hypercall clobbers %rdi,%rsi)
2050c88402SJoao Martins  */
2150c88402SJoao Martins 
2250c88402SJoao Martins /*
2350c88402SJoao Martins  * 64-bit segment selectors
2450c88402SJoao Martins  * These flat segments are in the Xen-private section of every GDT. Since these
2550c88402SJoao Martins  * are also present in the initial GDT, many OSes will be able to avoid
2650c88402SJoao Martins  * installing their own GDT.
2750c88402SJoao Martins  */
2850c88402SJoao Martins 
2950c88402SJoao Martins #define FLAT_RING3_CS32 0xe023  /* GDT index 260 */
3050c88402SJoao Martins #define FLAT_RING3_CS64 0xe033  /* GDT index 262 */
3150c88402SJoao Martins #define FLAT_RING3_DS32 0xe02b  /* GDT index 261 */
3250c88402SJoao Martins #define FLAT_RING3_DS64 0x0000  /* NULL selector */
3350c88402SJoao Martins #define FLAT_RING3_SS32 0xe02b  /* GDT index 261 */
3450c88402SJoao Martins #define FLAT_RING3_SS64 0xe02b  /* GDT index 261 */
3550c88402SJoao Martins 
3650c88402SJoao Martins #define FLAT_KERNEL_DS64 FLAT_RING3_DS64
3750c88402SJoao Martins #define FLAT_KERNEL_DS32 FLAT_RING3_DS32
3850c88402SJoao Martins #define FLAT_KERNEL_DS   FLAT_KERNEL_DS64
3950c88402SJoao Martins #define FLAT_KERNEL_CS64 FLAT_RING3_CS64
4050c88402SJoao Martins #define FLAT_KERNEL_CS32 FLAT_RING3_CS32
4150c88402SJoao Martins #define FLAT_KERNEL_CS   FLAT_KERNEL_CS64
4250c88402SJoao Martins #define FLAT_KERNEL_SS64 FLAT_RING3_SS64
4350c88402SJoao Martins #define FLAT_KERNEL_SS32 FLAT_RING3_SS32
4450c88402SJoao Martins #define FLAT_KERNEL_SS   FLAT_KERNEL_SS64
4550c88402SJoao Martins 
4650c88402SJoao Martins #define FLAT_USER_DS64 FLAT_RING3_DS64
4750c88402SJoao Martins #define FLAT_USER_DS32 FLAT_RING3_DS32
4850c88402SJoao Martins #define FLAT_USER_DS   FLAT_USER_DS64
4950c88402SJoao Martins #define FLAT_USER_CS64 FLAT_RING3_CS64
5050c88402SJoao Martins #define FLAT_USER_CS32 FLAT_RING3_CS32
5150c88402SJoao Martins #define FLAT_USER_CS   FLAT_USER_CS64
5250c88402SJoao Martins #define FLAT_USER_SS64 FLAT_RING3_SS64
5350c88402SJoao Martins #define FLAT_USER_SS32 FLAT_RING3_SS32
5450c88402SJoao Martins #define FLAT_USER_SS   FLAT_USER_SS64
5550c88402SJoao Martins 
5650c88402SJoao Martins #define __HYPERVISOR_VIRT_START 0xFFFF800000000000
5750c88402SJoao Martins #define __HYPERVISOR_VIRT_END   0xFFFF880000000000
5850c88402SJoao Martins #define __MACH2PHYS_VIRT_START  0xFFFF800000000000
5950c88402SJoao Martins #define __MACH2PHYS_VIRT_END    0xFFFF804000000000
6050c88402SJoao Martins 
6150c88402SJoao Martins #ifndef HYPERVISOR_VIRT_START
6250c88402SJoao Martins #define HYPERVISOR_VIRT_START xen_mk_ulong(__HYPERVISOR_VIRT_START)
6350c88402SJoao Martins #define HYPERVISOR_VIRT_END   xen_mk_ulong(__HYPERVISOR_VIRT_END)
6450c88402SJoao Martins #endif
6550c88402SJoao Martins 
6650c88402SJoao Martins #define MACH2PHYS_VIRT_START  xen_mk_ulong(__MACH2PHYS_VIRT_START)
6750c88402SJoao Martins #define MACH2PHYS_VIRT_END    xen_mk_ulong(__MACH2PHYS_VIRT_END)
6850c88402SJoao Martins #define MACH2PHYS_NR_ENTRIES  ((MACH2PHYS_VIRT_END-MACH2PHYS_VIRT_START)>>3)
6950c88402SJoao Martins #ifndef machine_to_phys_mapping
7050c88402SJoao Martins #define machine_to_phys_mapping ((unsigned long *)HYPERVISOR_VIRT_START)
7150c88402SJoao Martins #endif
7250c88402SJoao Martins 
7350c88402SJoao Martins /*
7450c88402SJoao Martins  * int HYPERVISOR_set_segment_base(unsigned int which, unsigned long base)
7550c88402SJoao Martins  *  @which == SEGBASE_*  ;  @base == 64-bit base address
7650c88402SJoao Martins  * Returns 0 on success.
7750c88402SJoao Martins  */
7850c88402SJoao Martins #define SEGBASE_FS          0
7950c88402SJoao Martins #define SEGBASE_GS_USER     1
8050c88402SJoao Martins #define SEGBASE_GS_KERNEL   2
8150c88402SJoao Martins #define SEGBASE_GS_USER_SEL 3 /* Set user %gs specified in base[15:0] */
8250c88402SJoao Martins 
8350c88402SJoao Martins /*
8450c88402SJoao Martins  * int HYPERVISOR_iret(void)
8550c88402SJoao Martins  * All arguments are on the kernel stack, in the following format.
8650c88402SJoao Martins  * Never returns if successful. Current kernel context is lost.
8750c88402SJoao Martins  * The saved CS is mapped as follows:
8850c88402SJoao Martins  *   RING0 -> RING3 kernel mode.
8950c88402SJoao Martins  *   RING1 -> RING3 kernel mode.
9050c88402SJoao Martins  *   RING2 -> RING3 kernel mode.
9150c88402SJoao Martins  *   RING3 -> RING3 user mode.
9250c88402SJoao Martins  * However RING0 indicates that the guest kernel should return to iteself
9350c88402SJoao Martins  * directly with
9450c88402SJoao Martins  *      orb   $3,1*8(%rsp)
9550c88402SJoao Martins  *      iretq
9650c88402SJoao Martins  * If flags contains VGCF_in_syscall:
9750c88402SJoao Martins  *   Restore RAX, RIP, RFLAGS, RSP.
9850c88402SJoao Martins  *   Discard R11, RCX, CS, SS.
9950c88402SJoao Martins  * Otherwise:
10050c88402SJoao Martins  *   Restore RAX, R11, RCX, CS:RIP, RFLAGS, SS:RSP.
10150c88402SJoao Martins  * All other registers are saved on hypercall entry and restored to user.
10250c88402SJoao Martins  */
10350c88402SJoao Martins /* Guest exited in SYSCALL context? Return to guest with SYSRET? */
10450c88402SJoao Martins #define _VGCF_in_syscall 8
10550c88402SJoao Martins #define VGCF_in_syscall  (1<<_VGCF_in_syscall)
10650c88402SJoao Martins #define VGCF_IN_SYSCALL  VGCF_in_syscall
10750c88402SJoao Martins 
10850c88402SJoao Martins #ifndef __ASSEMBLY__
10950c88402SJoao Martins 
11050c88402SJoao Martins struct iret_context {
11150c88402SJoao Martins     /* Top of stack (%rsp at point of hypercall). */
11250c88402SJoao Martins     uint64_t rax, r11, rcx, flags, rip, cs, rflags, rsp, ss;
11350c88402SJoao Martins     /* Bottom of iret stack frame. */
11450c88402SJoao Martins };
11550c88402SJoao Martins 
11650c88402SJoao Martins #if defined(__XEN__) || defined(__XEN_TOOLS__)
11750c88402SJoao Martins /* Anonymous unions include all permissible names (e.g., al/ah/ax/eax/rax). */
11850c88402SJoao Martins #define __DECL_REG_LOHI(which) union { \
11950c88402SJoao Martins     uint64_t r ## which ## x; \
12050c88402SJoao Martins     uint32_t e ## which ## x; \
12150c88402SJoao Martins     uint16_t which ## x; \
12250c88402SJoao Martins     struct { \
12350c88402SJoao Martins         uint8_t which ## l; \
12450c88402SJoao Martins         uint8_t which ## h; \
12550c88402SJoao Martins     }; \
12650c88402SJoao Martins }
12750c88402SJoao Martins #define __DECL_REG_LO8(name) union { \
12850c88402SJoao Martins     uint64_t r ## name; \
12950c88402SJoao Martins     uint32_t e ## name; \
13050c88402SJoao Martins     uint16_t name; \
13150c88402SJoao Martins     uint8_t name ## l; \
13250c88402SJoao Martins }
13350c88402SJoao Martins #define __DECL_REG_LO16(name) union { \
13450c88402SJoao Martins     uint64_t r ## name; \
13550c88402SJoao Martins     uint32_t e ## name; \
13650c88402SJoao Martins     uint16_t name; \
13750c88402SJoao Martins }
13850c88402SJoao Martins #define __DECL_REG_HI(num) union { \
13950c88402SJoao Martins     uint64_t r ## num; \
14050c88402SJoao Martins     uint32_t r ## num ## d; \
14150c88402SJoao Martins     uint16_t r ## num ## w; \
14250c88402SJoao Martins     uint8_t r ## num ## b; \
14350c88402SJoao Martins }
14450c88402SJoao Martins #elif defined(__GNUC__) && !defined(__STRICT_ANSI__)
14550c88402SJoao Martins /* Anonymous union includes both 32- and 64-bit names (e.g., eax/rax). */
14650c88402SJoao Martins #define __DECL_REG(name) union { \
14750c88402SJoao Martins     uint64_t r ## name, e ## name; \
14850c88402SJoao Martins     uint32_t _e ## name; \
14950c88402SJoao Martins }
15050c88402SJoao Martins #else
15150c88402SJoao Martins /* Non-gcc sources must always use the proper 64-bit name (e.g., rax). */
15250c88402SJoao Martins #define __DECL_REG(name) uint64_t r ## name
15350c88402SJoao Martins #endif
15450c88402SJoao Martins 
15550c88402SJoao Martins #ifndef __DECL_REG_LOHI
15650c88402SJoao Martins #define __DECL_REG_LOHI(name) __DECL_REG(name ## x)
15750c88402SJoao Martins #define __DECL_REG_LO8        __DECL_REG
15850c88402SJoao Martins #define __DECL_REG_LO16       __DECL_REG
15950c88402SJoao Martins #define __DECL_REG_HI(num)    uint64_t r ## num
16050c88402SJoao Martins #endif
16150c88402SJoao Martins 
16250c88402SJoao Martins struct cpu_user_regs {
16350c88402SJoao Martins     __DECL_REG_HI(15);
16450c88402SJoao Martins     __DECL_REG_HI(14);
16550c88402SJoao Martins     __DECL_REG_HI(13);
16650c88402SJoao Martins     __DECL_REG_HI(12);
16750c88402SJoao Martins     __DECL_REG_LO8(bp);
16850c88402SJoao Martins     __DECL_REG_LOHI(b);
16950c88402SJoao Martins     __DECL_REG_HI(11);
17050c88402SJoao Martins     __DECL_REG_HI(10);
17150c88402SJoao Martins     __DECL_REG_HI(9);
17250c88402SJoao Martins     __DECL_REG_HI(8);
17350c88402SJoao Martins     __DECL_REG_LOHI(a);
17450c88402SJoao Martins     __DECL_REG_LOHI(c);
17550c88402SJoao Martins     __DECL_REG_LOHI(d);
17650c88402SJoao Martins     __DECL_REG_LO8(si);
17750c88402SJoao Martins     __DECL_REG_LO8(di);
17850c88402SJoao Martins     uint32_t error_code;    /* private */
17950c88402SJoao Martins     uint32_t entry_vector;  /* private */
18050c88402SJoao Martins     __DECL_REG_LO16(ip);
18150c88402SJoao Martins     uint16_t cs, _pad0[1];
18250c88402SJoao Martins     uint8_t  saved_upcall_mask;
18350c88402SJoao Martins     uint8_t  _pad1[3];
18450c88402SJoao Martins     __DECL_REG_LO16(flags); /* rflags.IF == !saved_upcall_mask */
18550c88402SJoao Martins     __DECL_REG_LO8(sp);
18650c88402SJoao Martins     uint16_t ss, _pad2[3];
18750c88402SJoao Martins     uint16_t es, _pad3[3];
18850c88402SJoao Martins     uint16_t ds, _pad4[3];
18950c88402SJoao Martins     uint16_t fs, _pad5[3];
19050c88402SJoao Martins     uint16_t gs, _pad6[3];
19150c88402SJoao Martins };
19250c88402SJoao Martins typedef struct cpu_user_regs cpu_user_regs_t;
19350c88402SJoao Martins DEFINE_XEN_GUEST_HANDLE(cpu_user_regs_t);
19450c88402SJoao Martins 
19550c88402SJoao Martins #undef __DECL_REG
19650c88402SJoao Martins #undef __DECL_REG_LOHI
19750c88402SJoao Martins #undef __DECL_REG_LO8
19850c88402SJoao Martins #undef __DECL_REG_LO16
19950c88402SJoao Martins #undef __DECL_REG_HI
20050c88402SJoao Martins 
20150c88402SJoao Martins #define xen_pfn_to_cr3(pfn) ((unsigned long)(pfn) << 12)
20250c88402SJoao Martins #define xen_cr3_to_pfn(cr3) ((unsigned long)(cr3) >> 12)
20350c88402SJoao Martins 
20450c88402SJoao Martins struct arch_vcpu_info {
20550c88402SJoao Martins     unsigned long cr2;
20650c88402SJoao Martins     unsigned long pad; /* sizeof(vcpu_info_t) == 64 */
20750c88402SJoao Martins };
20850c88402SJoao Martins typedef struct arch_vcpu_info arch_vcpu_info_t;
20950c88402SJoao Martins 
21050c88402SJoao Martins typedef unsigned long xen_callback_t;
21150c88402SJoao Martins 
21250c88402SJoao Martins #endif /* !__ASSEMBLY__ */
21350c88402SJoao Martins 
21450c88402SJoao Martins #endif /* __XEN_PUBLIC_ARCH_X86_XEN_X86_64_H__ */
21550c88402SJoao Martins 
21650c88402SJoao Martins /*
21750c88402SJoao Martins  * Local variables:
21850c88402SJoao Martins  * mode: C
21950c88402SJoao Martins  * c-file-style: "BSD"
22050c88402SJoao Martins  * c-basic-offset: 4
22150c88402SJoao Martins  * tab-width: 4
22250c88402SJoao Martins  * indent-tabs-mode: nil
22350c88402SJoao Martins  * End:
22450c88402SJoao Martins  */
225