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