Import xen headers directly into GRUB
This commit is contained in:
parent
855fe6869c
commit
e07badcc31
14 changed files with 4035 additions and 0 deletions
171
include/xen/arch-x86/xen-x86_32.h
Normal file
171
include/xen/arch-x86/xen-x86_32.h
Normal file
|
@ -0,0 +1,171 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* xen-x86_32.h
|
||||||
|
*
|
||||||
|
* Guest OS interface to x86 32-bit Xen.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to
|
||||||
|
* deal in the Software without restriction, including without limitation the
|
||||||
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
* sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2004-2007, K A Fraser
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __XEN_PUBLIC_ARCH_X86_XEN_X86_32_H__
|
||||||
|
#define __XEN_PUBLIC_ARCH_X86_XEN_X86_32_H__
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Hypercall interface:
|
||||||
|
* Input: %ebx, %ecx, %edx, %esi, %edi, %ebp (arguments 1-6)
|
||||||
|
* Output: %eax
|
||||||
|
* Access is via hypercall page (set up by guest loader or via a Xen MSR):
|
||||||
|
* call hypercall_page + hypercall-number * 32
|
||||||
|
* Clobbered: Argument registers (e.g., 2-arg hypercall clobbers %ebx,%ecx)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These flat segments are in the Xen-private section of every GDT. Since these
|
||||||
|
* are also present in the initial GDT, many OSes will be able to avoid
|
||||||
|
* installing their own GDT.
|
||||||
|
*/
|
||||||
|
#define FLAT_RING1_CS 0xe019 /* GDT index 259 */
|
||||||
|
#define FLAT_RING1_DS 0xe021 /* GDT index 260 */
|
||||||
|
#define FLAT_RING1_SS 0xe021 /* GDT index 260 */
|
||||||
|
#define FLAT_RING3_CS 0xe02b /* GDT index 261 */
|
||||||
|
#define FLAT_RING3_DS 0xe033 /* GDT index 262 */
|
||||||
|
#define FLAT_RING3_SS 0xe033 /* GDT index 262 */
|
||||||
|
|
||||||
|
#define FLAT_KERNEL_CS FLAT_RING1_CS
|
||||||
|
#define FLAT_KERNEL_DS FLAT_RING1_DS
|
||||||
|
#define FLAT_KERNEL_SS FLAT_RING1_SS
|
||||||
|
#define FLAT_USER_CS FLAT_RING3_CS
|
||||||
|
#define FLAT_USER_DS FLAT_RING3_DS
|
||||||
|
#define FLAT_USER_SS FLAT_RING3_SS
|
||||||
|
|
||||||
|
#define __HYPERVISOR_VIRT_START_PAE 0xF5800000
|
||||||
|
#define __MACH2PHYS_VIRT_START_PAE 0xF5800000
|
||||||
|
#define __MACH2PHYS_VIRT_END_PAE 0xF6800000
|
||||||
|
#define HYPERVISOR_VIRT_START_PAE \
|
||||||
|
mk_unsigned_long(__HYPERVISOR_VIRT_START_PAE)
|
||||||
|
#define MACH2PHYS_VIRT_START_PAE \
|
||||||
|
mk_unsigned_long(__MACH2PHYS_VIRT_START_PAE)
|
||||||
|
#define MACH2PHYS_VIRT_END_PAE \
|
||||||
|
mk_unsigned_long(__MACH2PHYS_VIRT_END_PAE)
|
||||||
|
|
||||||
|
/* Non-PAE bounds are obsolete. */
|
||||||
|
#define __HYPERVISOR_VIRT_START_NONPAE 0xFC000000
|
||||||
|
#define __MACH2PHYS_VIRT_START_NONPAE 0xFC000000
|
||||||
|
#define __MACH2PHYS_VIRT_END_NONPAE 0xFC400000
|
||||||
|
#define HYPERVISOR_VIRT_START_NONPAE \
|
||||||
|
mk_unsigned_long(__HYPERVISOR_VIRT_START_NONPAE)
|
||||||
|
#define MACH2PHYS_VIRT_START_NONPAE \
|
||||||
|
mk_unsigned_long(__MACH2PHYS_VIRT_START_NONPAE)
|
||||||
|
#define MACH2PHYS_VIRT_END_NONPAE \
|
||||||
|
mk_unsigned_long(__MACH2PHYS_VIRT_END_NONPAE)
|
||||||
|
|
||||||
|
#define __HYPERVISOR_VIRT_START __HYPERVISOR_VIRT_START_PAE
|
||||||
|
#define __MACH2PHYS_VIRT_START __MACH2PHYS_VIRT_START_PAE
|
||||||
|
#define __MACH2PHYS_VIRT_END __MACH2PHYS_VIRT_END_PAE
|
||||||
|
|
||||||
|
#ifndef HYPERVISOR_VIRT_START
|
||||||
|
#define HYPERVISOR_VIRT_START mk_unsigned_long(__HYPERVISOR_VIRT_START)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MACH2PHYS_VIRT_START mk_unsigned_long(__MACH2PHYS_VIRT_START)
|
||||||
|
#define MACH2PHYS_VIRT_END mk_unsigned_long(__MACH2PHYS_VIRT_END)
|
||||||
|
#define MACH2PHYS_NR_ENTRIES ((MACH2PHYS_VIRT_END-MACH2PHYS_VIRT_START)>>2)
|
||||||
|
#ifndef machine_to_phys_mapping
|
||||||
|
#define machine_to_phys_mapping ((unsigned long *)MACH2PHYS_VIRT_START)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* 32-/64-bit invariability for control interfaces (domctl/sysctl). */
|
||||||
|
#if defined(__XEN__) || defined(__XEN_TOOLS__)
|
||||||
|
#undef ___DEFINE_XEN_GUEST_HANDLE
|
||||||
|
#define ___DEFINE_XEN_GUEST_HANDLE(name, type) \
|
||||||
|
typedef struct { type *p; } \
|
||||||
|
__guest_handle_ ## name; \
|
||||||
|
typedef struct { union { type *p; uint64_aligned_t q; }; } \
|
||||||
|
__guest_handle_64_ ## name
|
||||||
|
#undef set_xen_guest_handle_raw
|
||||||
|
#define set_xen_guest_handle_raw(hnd, val) \
|
||||||
|
do { if ( sizeof(hnd) == 8 ) *(uint64_t *)&(hnd) = 0; \
|
||||||
|
(hnd).p = val; \
|
||||||
|
} while ( 0 )
|
||||||
|
#define uint64_aligned_t uint64_t __attribute__((aligned(8)))
|
||||||
|
#define __XEN_GUEST_HANDLE_64(name) __guest_handle_64_ ## name
|
||||||
|
#define XEN_GUEST_HANDLE_64(name) __XEN_GUEST_HANDLE_64(name)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
|
struct cpu_user_regs {
|
||||||
|
uint32_t ebx;
|
||||||
|
uint32_t ecx;
|
||||||
|
uint32_t edx;
|
||||||
|
uint32_t esi;
|
||||||
|
uint32_t edi;
|
||||||
|
uint32_t ebp;
|
||||||
|
uint32_t eax;
|
||||||
|
uint16_t error_code; /* private */
|
||||||
|
uint16_t entry_vector; /* private */
|
||||||
|
uint32_t eip;
|
||||||
|
uint16_t cs;
|
||||||
|
uint8_t saved_upcall_mask;
|
||||||
|
uint8_t _pad0;
|
||||||
|
uint32_t eflags; /* eflags.IF == !saved_upcall_mask */
|
||||||
|
uint32_t esp;
|
||||||
|
uint16_t ss, _pad1;
|
||||||
|
uint16_t es, _pad2;
|
||||||
|
uint16_t ds, _pad3;
|
||||||
|
uint16_t fs, _pad4;
|
||||||
|
uint16_t gs, _pad5;
|
||||||
|
};
|
||||||
|
typedef struct cpu_user_regs cpu_user_regs_t;
|
||||||
|
DEFINE_XEN_GUEST_HANDLE(cpu_user_regs_t);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Page-directory addresses above 4GB do not fit into architectural %cr3.
|
||||||
|
* When accessing %cr3, or equivalent field in vcpu_guest_context, guests
|
||||||
|
* must use the following accessor macros to pack/unpack valid MFNs.
|
||||||
|
*/
|
||||||
|
#define xen_pfn_to_cr3(pfn) (((unsigned)(pfn) << 12) | ((unsigned)(pfn) >> 20))
|
||||||
|
#define xen_cr3_to_pfn(cr3) (((unsigned)(cr3) >> 12) | ((unsigned)(cr3) << 20))
|
||||||
|
|
||||||
|
struct arch_vcpu_info {
|
||||||
|
unsigned long cr2;
|
||||||
|
unsigned long pad[5]; /* sizeof(vcpu_info_t) == 64 */
|
||||||
|
};
|
||||||
|
typedef struct arch_vcpu_info arch_vcpu_info_t;
|
||||||
|
|
||||||
|
struct xen_callback {
|
||||||
|
unsigned long cs;
|
||||||
|
unsigned long eip;
|
||||||
|
};
|
||||||
|
typedef struct xen_callback xen_callback_t;
|
||||||
|
|
||||||
|
#endif /* !__ASSEMBLY__ */
|
||||||
|
|
||||||
|
#endif /* __XEN_PUBLIC_ARCH_X86_XEN_X86_32_H__ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local variables:
|
||||||
|
* mode: C
|
||||||
|
* c-file-style: "BSD"
|
||||||
|
* c-basic-offset: 4
|
||||||
|
* tab-width: 4
|
||||||
|
* indent-tabs-mode: nil
|
||||||
|
* End:
|
||||||
|
*/
|
202
include/xen/arch-x86/xen-x86_64.h
Normal file
202
include/xen/arch-x86/xen-x86_64.h
Normal file
|
@ -0,0 +1,202 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* xen-x86_64.h
|
||||||
|
*
|
||||||
|
* Guest OS interface to x86 64-bit Xen.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to
|
||||||
|
* deal in the Software without restriction, including without limitation the
|
||||||
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
* sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2004-2006, K A Fraser
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __XEN_PUBLIC_ARCH_X86_XEN_X86_64_H__
|
||||||
|
#define __XEN_PUBLIC_ARCH_X86_XEN_X86_64_H__
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Hypercall interface:
|
||||||
|
* Input: %rdi, %rsi, %rdx, %r10, %r8, %r9 (arguments 1-6)
|
||||||
|
* Output: %rax
|
||||||
|
* Access is via hypercall page (set up by guest loader or via a Xen MSR):
|
||||||
|
* call hypercall_page + hypercall-number * 32
|
||||||
|
* Clobbered: argument registers (e.g., 2-arg hypercall clobbers %rdi,%rsi)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 64-bit segment selectors
|
||||||
|
* These flat segments are in the Xen-private section of every GDT. Since these
|
||||||
|
* are also present in the initial GDT, many OSes will be able to avoid
|
||||||
|
* installing their own GDT.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define FLAT_RING3_CS32 0xe023 /* GDT index 260 */
|
||||||
|
#define FLAT_RING3_CS64 0xe033 /* GDT index 261 */
|
||||||
|
#define FLAT_RING3_DS32 0xe02b /* GDT index 262 */
|
||||||
|
#define FLAT_RING3_DS64 0x0000 /* NULL selector */
|
||||||
|
#define FLAT_RING3_SS32 0xe02b /* GDT index 262 */
|
||||||
|
#define FLAT_RING3_SS64 0xe02b /* GDT index 262 */
|
||||||
|
|
||||||
|
#define FLAT_KERNEL_DS64 FLAT_RING3_DS64
|
||||||
|
#define FLAT_KERNEL_DS32 FLAT_RING3_DS32
|
||||||
|
#define FLAT_KERNEL_DS FLAT_KERNEL_DS64
|
||||||
|
#define FLAT_KERNEL_CS64 FLAT_RING3_CS64
|
||||||
|
#define FLAT_KERNEL_CS32 FLAT_RING3_CS32
|
||||||
|
#define FLAT_KERNEL_CS FLAT_KERNEL_CS64
|
||||||
|
#define FLAT_KERNEL_SS64 FLAT_RING3_SS64
|
||||||
|
#define FLAT_KERNEL_SS32 FLAT_RING3_SS32
|
||||||
|
#define FLAT_KERNEL_SS FLAT_KERNEL_SS64
|
||||||
|
|
||||||
|
#define FLAT_USER_DS64 FLAT_RING3_DS64
|
||||||
|
#define FLAT_USER_DS32 FLAT_RING3_DS32
|
||||||
|
#define FLAT_USER_DS FLAT_USER_DS64
|
||||||
|
#define FLAT_USER_CS64 FLAT_RING3_CS64
|
||||||
|
#define FLAT_USER_CS32 FLAT_RING3_CS32
|
||||||
|
#define FLAT_USER_CS FLAT_USER_CS64
|
||||||
|
#define FLAT_USER_SS64 FLAT_RING3_SS64
|
||||||
|
#define FLAT_USER_SS32 FLAT_RING3_SS32
|
||||||
|
#define FLAT_USER_SS FLAT_USER_SS64
|
||||||
|
|
||||||
|
#define __HYPERVISOR_VIRT_START 0xFFFF800000000000
|
||||||
|
#define __HYPERVISOR_VIRT_END 0xFFFF880000000000
|
||||||
|
#define __MACH2PHYS_VIRT_START 0xFFFF800000000000
|
||||||
|
#define __MACH2PHYS_VIRT_END 0xFFFF804000000000
|
||||||
|
|
||||||
|
#ifndef HYPERVISOR_VIRT_START
|
||||||
|
#define HYPERVISOR_VIRT_START mk_unsigned_long(__HYPERVISOR_VIRT_START)
|
||||||
|
#define HYPERVISOR_VIRT_END mk_unsigned_long(__HYPERVISOR_VIRT_END)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MACH2PHYS_VIRT_START mk_unsigned_long(__MACH2PHYS_VIRT_START)
|
||||||
|
#define MACH2PHYS_VIRT_END mk_unsigned_long(__MACH2PHYS_VIRT_END)
|
||||||
|
#define MACH2PHYS_NR_ENTRIES ((MACH2PHYS_VIRT_END-MACH2PHYS_VIRT_START)>>3)
|
||||||
|
#ifndef machine_to_phys_mapping
|
||||||
|
#define machine_to_phys_mapping ((unsigned long *)HYPERVISOR_VIRT_START)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* int HYPERVISOR_set_segment_base(unsigned int which, unsigned long base)
|
||||||
|
* @which == SEGBASE_* ; @base == 64-bit base address
|
||||||
|
* Returns 0 on success.
|
||||||
|
*/
|
||||||
|
#define SEGBASE_FS 0
|
||||||
|
#define SEGBASE_GS_USER 1
|
||||||
|
#define SEGBASE_GS_KERNEL 2
|
||||||
|
#define SEGBASE_GS_USER_SEL 3 /* Set user %gs specified in base[15:0] */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* int HYPERVISOR_iret(void)
|
||||||
|
* All arguments are on the kernel stack, in the following format.
|
||||||
|
* Never returns if successful. Current kernel context is lost.
|
||||||
|
* The saved CS is mapped as follows:
|
||||||
|
* RING0 -> RING3 kernel mode.
|
||||||
|
* RING1 -> RING3 kernel mode.
|
||||||
|
* RING2 -> RING3 kernel mode.
|
||||||
|
* RING3 -> RING3 user mode.
|
||||||
|
* However RING0 indicates that the guest kernel should return to iteself
|
||||||
|
* directly with
|
||||||
|
* orb $3,1*8(%rsp)
|
||||||
|
* iretq
|
||||||
|
* If flags contains VGCF_in_syscall:
|
||||||
|
* Restore RAX, RIP, RFLAGS, RSP.
|
||||||
|
* Discard R11, RCX, CS, SS.
|
||||||
|
* Otherwise:
|
||||||
|
* Restore RAX, R11, RCX, CS:RIP, RFLAGS, SS:RSP.
|
||||||
|
* All other registers are saved on hypercall entry and restored to user.
|
||||||
|
*/
|
||||||
|
/* Guest exited in SYSCALL context? Return to guest with SYSRET? */
|
||||||
|
#define _VGCF_in_syscall 8
|
||||||
|
#define VGCF_in_syscall (1<<_VGCF_in_syscall)
|
||||||
|
#define VGCF_IN_SYSCALL VGCF_in_syscall
|
||||||
|
|
||||||
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
|
struct iret_context {
|
||||||
|
/* Top of stack (%rsp at point of hypercall). */
|
||||||
|
uint64_t rax, r11, rcx, flags, rip, cs, rflags, rsp, ss;
|
||||||
|
/* Bottom of iret stack frame. */
|
||||||
|
};
|
||||||
|
|
||||||
|
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
||||||
|
/* Anonymous union includes both 32- and 64-bit names (e.g., eax/rax). */
|
||||||
|
#define __DECL_REG(name) union { \
|
||||||
|
uint64_t r ## name, e ## name; \
|
||||||
|
uint32_t _e ## name; \
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/* Non-gcc sources must always use the proper 64-bit name (e.g., rax). */
|
||||||
|
#define __DECL_REG(name) uint64_t r ## name
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct cpu_user_regs {
|
||||||
|
uint64_t r15;
|
||||||
|
uint64_t r14;
|
||||||
|
uint64_t r13;
|
||||||
|
uint64_t r12;
|
||||||
|
__DECL_REG(bp);
|
||||||
|
__DECL_REG(bx);
|
||||||
|
uint64_t r11;
|
||||||
|
uint64_t r10;
|
||||||
|
uint64_t r9;
|
||||||
|
uint64_t r8;
|
||||||
|
__DECL_REG(ax);
|
||||||
|
__DECL_REG(cx);
|
||||||
|
__DECL_REG(dx);
|
||||||
|
__DECL_REG(si);
|
||||||
|
__DECL_REG(di);
|
||||||
|
uint32_t error_code; /* private */
|
||||||
|
uint32_t entry_vector; /* private */
|
||||||
|
__DECL_REG(ip);
|
||||||
|
uint16_t cs, _pad0[1];
|
||||||
|
uint8_t saved_upcall_mask;
|
||||||
|
uint8_t _pad1[3];
|
||||||
|
__DECL_REG(flags); /* rflags.IF == !saved_upcall_mask */
|
||||||
|
__DECL_REG(sp);
|
||||||
|
uint16_t ss, _pad2[3];
|
||||||
|
uint16_t es, _pad3[3];
|
||||||
|
uint16_t ds, _pad4[3];
|
||||||
|
uint16_t fs, _pad5[3]; /* Non-zero => takes precedence over fs_base. */
|
||||||
|
uint16_t gs, _pad6[3]; /* Non-zero => takes precedence over gs_base_usr. */
|
||||||
|
};
|
||||||
|
typedef struct cpu_user_regs cpu_user_regs_t;
|
||||||
|
DEFINE_XEN_GUEST_HANDLE(cpu_user_regs_t);
|
||||||
|
|
||||||
|
#undef __DECL_REG
|
||||||
|
|
||||||
|
#define xen_pfn_to_cr3(pfn) ((unsigned long)(pfn) << 12)
|
||||||
|
#define xen_cr3_to_pfn(cr3) ((unsigned long)(cr3) >> 12)
|
||||||
|
|
||||||
|
struct arch_vcpu_info {
|
||||||
|
unsigned long cr2;
|
||||||
|
unsigned long pad; /* sizeof(vcpu_info_t) == 64 */
|
||||||
|
};
|
||||||
|
typedef struct arch_vcpu_info arch_vcpu_info_t;
|
||||||
|
|
||||||
|
typedef unsigned long xen_callback_t;
|
||||||
|
|
||||||
|
#endif /* !__ASSEMBLY__ */
|
||||||
|
|
||||||
|
#endif /* __XEN_PUBLIC_ARCH_X86_XEN_X86_64_H__ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local variables:
|
||||||
|
* mode: C
|
||||||
|
* c-file-style: "BSD"
|
||||||
|
* c-basic-offset: 4
|
||||||
|
* tab-width: 4
|
||||||
|
* indent-tabs-mode: nil
|
||||||
|
* End:
|
||||||
|
*/
|
273
include/xen/arch-x86/xen.h
Normal file
273
include/xen/arch-x86/xen.h
Normal file
|
@ -0,0 +1,273 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* arch-x86/xen.h
|
||||||
|
*
|
||||||
|
* Guest OS interface to x86 Xen.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to
|
||||||
|
* deal in the Software without restriction, including without limitation the
|
||||||
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
* sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2004-2006, K A Fraser
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../xen.h"
|
||||||
|
|
||||||
|
#ifndef __XEN_PUBLIC_ARCH_X86_XEN_H__
|
||||||
|
#define __XEN_PUBLIC_ARCH_X86_XEN_H__
|
||||||
|
|
||||||
|
/* Structural guest handles introduced in 0x00030201. */
|
||||||
|
#if __XEN_INTERFACE_VERSION__ >= 0x00030201
|
||||||
|
#define ___DEFINE_XEN_GUEST_HANDLE(name, type) \
|
||||||
|
typedef struct { type *p; } __guest_handle_ ## name
|
||||||
|
#else
|
||||||
|
#define ___DEFINE_XEN_GUEST_HANDLE(name, type) \
|
||||||
|
typedef type * __guest_handle_ ## name
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XEN_GUEST_HANDLE represents a guest pointer, when passed as a field
|
||||||
|
* in a struct in memory.
|
||||||
|
* XEN_GUEST_HANDLE_PARAM represent a guest pointer, when passed as an
|
||||||
|
* hypercall argument.
|
||||||
|
* XEN_GUEST_HANDLE_PARAM and XEN_GUEST_HANDLE are the same on X86 but
|
||||||
|
* they might not be on other architectures.
|
||||||
|
*/
|
||||||
|
#define __DEFINE_XEN_GUEST_HANDLE(name, type) \
|
||||||
|
___DEFINE_XEN_GUEST_HANDLE(name, type); \
|
||||||
|
___DEFINE_XEN_GUEST_HANDLE(const_##name, const type)
|
||||||
|
#define DEFINE_XEN_GUEST_HANDLE(name) __DEFINE_XEN_GUEST_HANDLE(name, name)
|
||||||
|
#define __XEN_GUEST_HANDLE(name) __guest_handle_ ## name
|
||||||
|
#define XEN_GUEST_HANDLE(name) __XEN_GUEST_HANDLE(name)
|
||||||
|
#define XEN_GUEST_HANDLE_PARAM(name) XEN_GUEST_HANDLE(name)
|
||||||
|
#define set_xen_guest_handle_raw(hnd, val) do { (hnd).p = val; } while (0)
|
||||||
|
#ifdef __XEN_TOOLS__
|
||||||
|
#define get_xen_guest_handle(val, hnd) do { val = (hnd).p; } while (0)
|
||||||
|
#endif
|
||||||
|
#define set_xen_guest_handle(hnd, val) set_xen_guest_handle_raw(hnd, val)
|
||||||
|
|
||||||
|
#if defined(__i386__)
|
||||||
|
#include "xen-x86_32.h"
|
||||||
|
#elif defined(__x86_64__)
|
||||||
|
#include "xen-x86_64.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __ASSEMBLY__
|
||||||
|
typedef unsigned long xen_pfn_t;
|
||||||
|
#define PRI_xen_pfn "lx"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define XEN_HAVE_PV_GUEST_ENTRY 1
|
||||||
|
|
||||||
|
#define XEN_HAVE_PV_UPCALL_MASK 1
|
||||||
|
|
||||||
|
/*
|
||||||
|
* `incontents 200 segdesc Segment Descriptor Tables
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* ` enum neg_errnoval
|
||||||
|
* ` HYPERVISOR_set_gdt(const xen_pfn_t frames[], unsigned int entries);
|
||||||
|
* `
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* A number of GDT entries are reserved by Xen. These are not situated at the
|
||||||
|
* start of the GDT because some stupid OSes export hard-coded selector values
|
||||||
|
* in their ABI. These hard-coded values are always near the start of the GDT,
|
||||||
|
* so Xen places itself out of the way, at the far end of the GDT.
|
||||||
|
*
|
||||||
|
* NB The LDT is set using the MMUEXT_SET_LDT op of HYPERVISOR_mmuext_op
|
||||||
|
*/
|
||||||
|
#define FIRST_RESERVED_GDT_PAGE 14
|
||||||
|
#define FIRST_RESERVED_GDT_BYTE (FIRST_RESERVED_GDT_PAGE * 4096)
|
||||||
|
#define FIRST_RESERVED_GDT_ENTRY (FIRST_RESERVED_GDT_BYTE / 8)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ` enum neg_errnoval
|
||||||
|
* ` HYPERVISOR_update_descriptor(u64 pa, u64 desc);
|
||||||
|
* `
|
||||||
|
* ` @pa The machine physical address of the descriptor to
|
||||||
|
* ` update. Must be either a descriptor page or writable.
|
||||||
|
* ` @desc The descriptor value to update, in the same format as a
|
||||||
|
* ` native descriptor table entry.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Maximum number of virtual CPUs in legacy multi-processor guests. */
|
||||||
|
#define XEN_LEGACY_MAX_VCPUS 32
|
||||||
|
|
||||||
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
|
typedef unsigned long xen_ulong_t;
|
||||||
|
#define PRI_xen_ulong "lx"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ` enum neg_errnoval
|
||||||
|
* ` HYPERVISOR_stack_switch(unsigned long ss, unsigned long esp);
|
||||||
|
* `
|
||||||
|
* Sets the stack segment and pointer for the current vcpu.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ` enum neg_errnoval
|
||||||
|
* ` HYPERVISOR_set_trap_table(const struct trap_info traps[]);
|
||||||
|
* `
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Send an array of these to HYPERVISOR_set_trap_table().
|
||||||
|
* Terminate the array with a sentinel entry, with traps[].address==0.
|
||||||
|
* The privilege level specifies which modes may enter a trap via a software
|
||||||
|
* interrupt. On x86/64, since rings 1 and 2 are unavailable, we allocate
|
||||||
|
* privilege levels as follows:
|
||||||
|
* Level == 0: Noone may enter
|
||||||
|
* Level == 1: Kernel may enter
|
||||||
|
* Level == 2: Kernel may enter
|
||||||
|
* Level == 3: Everyone may enter
|
||||||
|
*/
|
||||||
|
#define TI_GET_DPL(_ti) ((_ti)->flags & 3)
|
||||||
|
#define TI_GET_IF(_ti) ((_ti)->flags & 4)
|
||||||
|
#define TI_SET_DPL(_ti,_dpl) ((_ti)->flags |= (_dpl))
|
||||||
|
#define TI_SET_IF(_ti,_if) ((_ti)->flags |= ((!!(_if))<<2))
|
||||||
|
struct trap_info {
|
||||||
|
uint8_t vector; /* exception vector */
|
||||||
|
uint8_t flags; /* 0-3: privilege level; 4: clear event enable? */
|
||||||
|
uint16_t cs; /* code selector */
|
||||||
|
unsigned long address; /* code offset */
|
||||||
|
};
|
||||||
|
typedef struct trap_info trap_info_t;
|
||||||
|
DEFINE_XEN_GUEST_HANDLE(trap_info_t);
|
||||||
|
|
||||||
|
typedef uint64_t tsc_timestamp_t; /* RDTSC timestamp */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The following is all CPU context. Note that the fpu_ctxt block is filled
|
||||||
|
* in by FXSAVE if the CPU has feature FXSR; otherwise FSAVE is used.
|
||||||
|
*
|
||||||
|
* Also note that when calling DOMCTL_setvcpucontext and VCPU_initialise
|
||||||
|
* for HVM and PVH guests, not all information in this structure is updated:
|
||||||
|
*
|
||||||
|
* - For HVM guests, the structures read include: fpu_ctxt (if
|
||||||
|
* VGCT_I387_VALID is set), flags, user_regs, debugreg[*]
|
||||||
|
*
|
||||||
|
* - PVH guests are the same as HVM guests, but additionally use ctrlreg[3] to
|
||||||
|
* set cr3. All other fields not used should be set to 0.
|
||||||
|
*/
|
||||||
|
struct vcpu_guest_context {
|
||||||
|
/* FPU registers come first so they can be aligned for FXSAVE/FXRSTOR. */
|
||||||
|
struct { char x[512]; } fpu_ctxt; /* User-level FPU registers */
|
||||||
|
#define VGCF_I387_VALID (1<<0)
|
||||||
|
#define VGCF_IN_KERNEL (1<<2)
|
||||||
|
#define _VGCF_i387_valid 0
|
||||||
|
#define VGCF_i387_valid (1<<_VGCF_i387_valid)
|
||||||
|
#define _VGCF_in_kernel 2
|
||||||
|
#define VGCF_in_kernel (1<<_VGCF_in_kernel)
|
||||||
|
#define _VGCF_failsafe_disables_events 3
|
||||||
|
#define VGCF_failsafe_disables_events (1<<_VGCF_failsafe_disables_events)
|
||||||
|
#define _VGCF_syscall_disables_events 4
|
||||||
|
#define VGCF_syscall_disables_events (1<<_VGCF_syscall_disables_events)
|
||||||
|
#define _VGCF_online 5
|
||||||
|
#define VGCF_online (1<<_VGCF_online)
|
||||||
|
unsigned long flags; /* VGCF_* flags */
|
||||||
|
struct cpu_user_regs user_regs; /* User-level CPU registers */
|
||||||
|
struct trap_info trap_ctxt[256]; /* Virtual IDT */
|
||||||
|
unsigned long ldt_base, ldt_ents; /* LDT (linear address, # ents) */
|
||||||
|
unsigned long gdt_frames[16], gdt_ents; /* GDT (machine frames, # ents) */
|
||||||
|
unsigned long kernel_ss, kernel_sp; /* Virtual TSS (only SS1/SP1) */
|
||||||
|
/* NB. User pagetable on x86/64 is placed in ctrlreg[1]. */
|
||||||
|
unsigned long ctrlreg[8]; /* CR0-CR7 (control registers) */
|
||||||
|
unsigned long debugreg[8]; /* DB0-DB7 (debug registers) */
|
||||||
|
#ifdef __i386__
|
||||||
|
unsigned long event_callback_cs; /* CS:EIP of event callback */
|
||||||
|
unsigned long event_callback_eip;
|
||||||
|
unsigned long failsafe_callback_cs; /* CS:EIP of failsafe callback */
|
||||||
|
unsigned long failsafe_callback_eip;
|
||||||
|
#else
|
||||||
|
unsigned long event_callback_eip;
|
||||||
|
unsigned long failsafe_callback_eip;
|
||||||
|
#ifdef __XEN__
|
||||||
|
union {
|
||||||
|
unsigned long syscall_callback_eip;
|
||||||
|
struct {
|
||||||
|
unsigned int event_callback_cs; /* compat CS of event cb */
|
||||||
|
unsigned int failsafe_callback_cs; /* compat CS of failsafe cb */
|
||||||
|
};
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
unsigned long syscall_callback_eip;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
unsigned long vm_assist; /* VMASST_TYPE_* bitmap */
|
||||||
|
#ifdef __x86_64__
|
||||||
|
/* Segment base addresses. */
|
||||||
|
uint64_t fs_base;
|
||||||
|
uint64_t gs_base_kernel;
|
||||||
|
uint64_t gs_base_user;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
typedef struct vcpu_guest_context vcpu_guest_context_t;
|
||||||
|
DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t);
|
||||||
|
|
||||||
|
struct arch_shared_info {
|
||||||
|
unsigned long max_pfn; /* max pfn that appears in table */
|
||||||
|
/* Frame containing list of mfns containing list of mfns containing p2m. */
|
||||||
|
xen_pfn_t pfn_to_mfn_frame_list_list;
|
||||||
|
unsigned long nmi_reason;
|
||||||
|
uint64_t pad[32];
|
||||||
|
};
|
||||||
|
typedef struct arch_shared_info arch_shared_info_t;
|
||||||
|
|
||||||
|
#endif /* !__ASSEMBLY__ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ` enum neg_errnoval
|
||||||
|
* ` HYPERVISOR_fpu_taskswitch(int set);
|
||||||
|
* `
|
||||||
|
* Sets (if set!=0) or clears (if set==0) CR0.TS.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ` enum neg_errnoval
|
||||||
|
* ` HYPERVISOR_set_debugreg(int regno, unsigned long value);
|
||||||
|
*
|
||||||
|
* ` unsigned long
|
||||||
|
* ` HYPERVISOR_get_debugreg(int regno);
|
||||||
|
* For 0<=reg<=7, returns the debug register value.
|
||||||
|
* For other values of reg, returns ((unsigned long)-EINVAL).
|
||||||
|
* (Unfortunately, this interface is defective.)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prefix forces emulation of some non-trapping instructions.
|
||||||
|
* Currently only CPUID.
|
||||||
|
*/
|
||||||
|
#ifdef __ASSEMBLY__
|
||||||
|
#define XEN_EMULATE_PREFIX .byte 0x0f,0x0b,0x78,0x65,0x6e ;
|
||||||
|
#define XEN_CPUID XEN_EMULATE_PREFIX cpuid
|
||||||
|
#else
|
||||||
|
#define XEN_EMULATE_PREFIX ".byte 0x0f,0x0b,0x78,0x65,0x6e ; "
|
||||||
|
#define XEN_CPUID XEN_EMULATE_PREFIX "cpuid"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __XEN_PUBLIC_ARCH_X86_XEN_H__ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local variables:
|
||||||
|
* mode: C
|
||||||
|
* c-file-style: "BSD"
|
||||||
|
* c-basic-offset: 4
|
||||||
|
* tab-width: 4
|
||||||
|
* indent-tabs-mode: nil
|
||||||
|
* End:
|
||||||
|
*/
|
381
include/xen/event_channel.h
Normal file
381
include/xen/event_channel.h
Normal file
|
@ -0,0 +1,381 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* event_channel.h
|
||||||
|
*
|
||||||
|
* Event channels between domains.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to
|
||||||
|
* deal in the Software without restriction, including without limitation the
|
||||||
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
* sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2003-2004, K A Fraser.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __XEN_PUBLIC_EVENT_CHANNEL_H__
|
||||||
|
#define __XEN_PUBLIC_EVENT_CHANNEL_H__
|
||||||
|
|
||||||
|
#include "xen.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* `incontents 150 evtchn Event Channels
|
||||||
|
*
|
||||||
|
* Event channels are the basic primitive provided by Xen for event
|
||||||
|
* notifications. An event is the Xen equivalent of a hardware
|
||||||
|
* interrupt. They essentially store one bit of information, the event
|
||||||
|
* of interest is signalled by transitioning this bit from 0 to 1.
|
||||||
|
*
|
||||||
|
* Notifications are received by a guest via an upcall from Xen,
|
||||||
|
* indicating when an event arrives (setting the bit). Further
|
||||||
|
* notifications are masked until the bit is cleared again (therefore,
|
||||||
|
* guests must check the value of the bit after re-enabling event
|
||||||
|
* delivery to ensure no missed notifications).
|
||||||
|
*
|
||||||
|
* Event notifications can be masked by setting a flag; this is
|
||||||
|
* equivalent to disabling interrupts and can be used to ensure
|
||||||
|
* atomicity of certain operations in the guest kernel.
|
||||||
|
*
|
||||||
|
* Event channels are represented by the evtchn_* fields in
|
||||||
|
* struct shared_info and struct vcpu_info.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ` enum neg_errnoval
|
||||||
|
* ` HYPERVISOR_event_channel_op(enum event_channel_op cmd, void *args)
|
||||||
|
* `
|
||||||
|
* @cmd == EVTCHNOP_* (event-channel operation).
|
||||||
|
* @args == struct evtchn_* Operation-specific extra arguments (NULL if none).
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ` enum event_channel_op { // EVTCHNOP_* => struct evtchn_* */
|
||||||
|
#define EVTCHNOP_bind_interdomain 0
|
||||||
|
#define EVTCHNOP_bind_virq 1
|
||||||
|
#define EVTCHNOP_bind_pirq 2
|
||||||
|
#define EVTCHNOP_close 3
|
||||||
|
#define EVTCHNOP_send 4
|
||||||
|
#define EVTCHNOP_status 5
|
||||||
|
#define EVTCHNOP_alloc_unbound 6
|
||||||
|
#define EVTCHNOP_bind_ipi 7
|
||||||
|
#define EVTCHNOP_bind_vcpu 8
|
||||||
|
#define EVTCHNOP_unmask 9
|
||||||
|
#define EVTCHNOP_reset 10
|
||||||
|
#define EVTCHNOP_init_control 11
|
||||||
|
#define EVTCHNOP_expand_array 12
|
||||||
|
#define EVTCHNOP_set_priority 13
|
||||||
|
/* ` } */
|
||||||
|
|
||||||
|
typedef uint32_t evtchn_port_t;
|
||||||
|
DEFINE_XEN_GUEST_HANDLE(evtchn_port_t);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* EVTCHNOP_alloc_unbound: Allocate a port in domain <dom> and mark as
|
||||||
|
* accepting interdomain bindings from domain <remote_dom>. A fresh port
|
||||||
|
* is allocated in <dom> and returned as <port>.
|
||||||
|
* NOTES:
|
||||||
|
* 1. If the caller is unprivileged then <dom> must be DOMID_SELF.
|
||||||
|
* 2. <rdom> may be DOMID_SELF, allowing loopback connections.
|
||||||
|
*/
|
||||||
|
struct evtchn_alloc_unbound {
|
||||||
|
/* IN parameters */
|
||||||
|
domid_t dom, remote_dom;
|
||||||
|
/* OUT parameters */
|
||||||
|
evtchn_port_t port;
|
||||||
|
};
|
||||||
|
typedef struct evtchn_alloc_unbound evtchn_alloc_unbound_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* EVTCHNOP_bind_interdomain: Construct an interdomain event channel between
|
||||||
|
* the calling domain and <remote_dom>. <remote_dom,remote_port> must identify
|
||||||
|
* a port that is unbound and marked as accepting bindings from the calling
|
||||||
|
* domain. A fresh port is allocated in the calling domain and returned as
|
||||||
|
* <local_port>.
|
||||||
|
*
|
||||||
|
* In case the peer domain has already tried to set our event channel
|
||||||
|
* pending, before it was bound, EVTCHNOP_bind_interdomain always sets
|
||||||
|
* the local event channel pending.
|
||||||
|
*
|
||||||
|
* The usual pattern of use, in the guest's upcall (or subsequent
|
||||||
|
* handler) is as follows: (Re-enable the event channel for subsequent
|
||||||
|
* signalling and then) check for the existence of whatever condition
|
||||||
|
* is being waited for by other means, and take whatever action is
|
||||||
|
* needed (if any).
|
||||||
|
*
|
||||||
|
* NOTES:
|
||||||
|
* 1. <remote_dom> may be DOMID_SELF, allowing loopback connections.
|
||||||
|
*/
|
||||||
|
struct evtchn_bind_interdomain {
|
||||||
|
/* IN parameters. */
|
||||||
|
domid_t remote_dom;
|
||||||
|
evtchn_port_t remote_port;
|
||||||
|
/* OUT parameters. */
|
||||||
|
evtchn_port_t local_port;
|
||||||
|
};
|
||||||
|
typedef struct evtchn_bind_interdomain evtchn_bind_interdomain_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* EVTCHNOP_bind_virq: Bind a local event channel to VIRQ <irq> on specified
|
||||||
|
* vcpu.
|
||||||
|
* NOTES:
|
||||||
|
* 1. Virtual IRQs are classified as per-vcpu or global. See the VIRQ list
|
||||||
|
* in xen.h for the classification of each VIRQ.
|
||||||
|
* 2. Global VIRQs must be allocated on VCPU0 but can subsequently be
|
||||||
|
* re-bound via EVTCHNOP_bind_vcpu.
|
||||||
|
* 3. Per-vcpu VIRQs may be bound to at most one event channel per vcpu.
|
||||||
|
* The allocated event channel is bound to the specified vcpu and the
|
||||||
|
* binding cannot be changed.
|
||||||
|
*/
|
||||||
|
struct evtchn_bind_virq {
|
||||||
|
/* IN parameters. */
|
||||||
|
uint32_t virq; /* enum virq */
|
||||||
|
uint32_t vcpu;
|
||||||
|
/* OUT parameters. */
|
||||||
|
evtchn_port_t port;
|
||||||
|
};
|
||||||
|
typedef struct evtchn_bind_virq evtchn_bind_virq_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* EVTCHNOP_bind_pirq: Bind a local event channel to a real IRQ (PIRQ <irq>).
|
||||||
|
* NOTES:
|
||||||
|
* 1. A physical IRQ may be bound to at most one event channel per domain.
|
||||||
|
* 2. Only a sufficiently-privileged domain may bind to a physical IRQ.
|
||||||
|
*/
|
||||||
|
struct evtchn_bind_pirq {
|
||||||
|
/* IN parameters. */
|
||||||
|
uint32_t pirq;
|
||||||
|
#define BIND_PIRQ__WILL_SHARE 1
|
||||||
|
uint32_t flags; /* BIND_PIRQ__* */
|
||||||
|
/* OUT parameters. */
|
||||||
|
evtchn_port_t port;
|
||||||
|
};
|
||||||
|
typedef struct evtchn_bind_pirq evtchn_bind_pirq_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* EVTCHNOP_bind_ipi: Bind a local event channel to receive events.
|
||||||
|
* NOTES:
|
||||||
|
* 1. The allocated event channel is bound to the specified vcpu. The binding
|
||||||
|
* may not be changed.
|
||||||
|
*/
|
||||||
|
struct evtchn_bind_ipi {
|
||||||
|
uint32_t vcpu;
|
||||||
|
/* OUT parameters. */
|
||||||
|
evtchn_port_t port;
|
||||||
|
};
|
||||||
|
typedef struct evtchn_bind_ipi evtchn_bind_ipi_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* EVTCHNOP_close: Close a local event channel <port>. If the channel is
|
||||||
|
* interdomain then the remote end is placed in the unbound state
|
||||||
|
* (EVTCHNSTAT_unbound), awaiting a new connection.
|
||||||
|
*/
|
||||||
|
struct evtchn_close {
|
||||||
|
/* IN parameters. */
|
||||||
|
evtchn_port_t port;
|
||||||
|
};
|
||||||
|
typedef struct evtchn_close evtchn_close_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* EVTCHNOP_send: Send an event to the remote end of the channel whose local
|
||||||
|
* endpoint is <port>.
|
||||||
|
*/
|
||||||
|
struct evtchn_send {
|
||||||
|
/* IN parameters. */
|
||||||
|
evtchn_port_t port;
|
||||||
|
};
|
||||||
|
typedef struct evtchn_send evtchn_send_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* EVTCHNOP_status: Get the current status of the communication channel which
|
||||||
|
* has an endpoint at <dom, port>.
|
||||||
|
* NOTES:
|
||||||
|
* 1. <dom> may be specified as DOMID_SELF.
|
||||||
|
* 2. Only a sufficiently-privileged domain may obtain the status of an event
|
||||||
|
* channel for which <dom> is not DOMID_SELF.
|
||||||
|
*/
|
||||||
|
struct evtchn_status {
|
||||||
|
/* IN parameters */
|
||||||
|
domid_t dom;
|
||||||
|
evtchn_port_t port;
|
||||||
|
/* OUT parameters */
|
||||||
|
#define EVTCHNSTAT_closed 0 /* Channel is not in use. */
|
||||||
|
#define EVTCHNSTAT_unbound 1 /* Channel is waiting interdom connection.*/
|
||||||
|
#define EVTCHNSTAT_interdomain 2 /* Channel is connected to remote domain. */
|
||||||
|
#define EVTCHNSTAT_pirq 3 /* Channel is bound to a phys IRQ line. */
|
||||||
|
#define EVTCHNSTAT_virq 4 /* Channel is bound to a virtual IRQ line */
|
||||||
|
#define EVTCHNSTAT_ipi 5 /* Channel is bound to a virtual IPI line */
|
||||||
|
uint32_t status;
|
||||||
|
uint32_t vcpu; /* VCPU to which this channel is bound. */
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
domid_t dom;
|
||||||
|
} unbound; /* EVTCHNSTAT_unbound */
|
||||||
|
struct {
|
||||||
|
domid_t dom;
|
||||||
|
evtchn_port_t port;
|
||||||
|
} interdomain; /* EVTCHNSTAT_interdomain */
|
||||||
|
uint32_t pirq; /* EVTCHNSTAT_pirq */
|
||||||
|
uint32_t virq; /* EVTCHNSTAT_virq */
|
||||||
|
} u;
|
||||||
|
};
|
||||||
|
typedef struct evtchn_status evtchn_status_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* EVTCHNOP_bind_vcpu: Specify which vcpu a channel should notify when an
|
||||||
|
* event is pending.
|
||||||
|
* NOTES:
|
||||||
|
* 1. IPI-bound channels always notify the vcpu specified at bind time.
|
||||||
|
* This binding cannot be changed.
|
||||||
|
* 2. Per-VCPU VIRQ channels always notify the vcpu specified at bind time.
|
||||||
|
* This binding cannot be changed.
|
||||||
|
* 3. All other channels notify vcpu0 by default. This default is set when
|
||||||
|
* the channel is allocated (a port that is freed and subsequently reused
|
||||||
|
* has its binding reset to vcpu0).
|
||||||
|
*/
|
||||||
|
struct evtchn_bind_vcpu {
|
||||||
|
/* IN parameters. */
|
||||||
|
evtchn_port_t port;
|
||||||
|
uint32_t vcpu;
|
||||||
|
};
|
||||||
|
typedef struct evtchn_bind_vcpu evtchn_bind_vcpu_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* EVTCHNOP_unmask: Unmask the specified local event-channel port and deliver
|
||||||
|
* a notification to the appropriate VCPU if an event is pending.
|
||||||
|
*/
|
||||||
|
struct evtchn_unmask {
|
||||||
|
/* IN parameters. */
|
||||||
|
evtchn_port_t port;
|
||||||
|
};
|
||||||
|
typedef struct evtchn_unmask evtchn_unmask_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* EVTCHNOP_reset: Close all event channels associated with specified domain.
|
||||||
|
* NOTES:
|
||||||
|
* 1. <dom> may be specified as DOMID_SELF.
|
||||||
|
* 2. Only a sufficiently-privileged domain may specify other than DOMID_SELF.
|
||||||
|
*/
|
||||||
|
struct evtchn_reset {
|
||||||
|
/* IN parameters. */
|
||||||
|
domid_t dom;
|
||||||
|
};
|
||||||
|
typedef struct evtchn_reset evtchn_reset_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* EVTCHNOP_init_control: initialize the control block for the FIFO ABI.
|
||||||
|
*
|
||||||
|
* Note: any events that are currently pending will not be resent and
|
||||||
|
* will be lost. Guests should call this before binding any event to
|
||||||
|
* avoid losing any events.
|
||||||
|
*/
|
||||||
|
struct evtchn_init_control {
|
||||||
|
/* IN parameters. */
|
||||||
|
uint64_t control_gfn;
|
||||||
|
uint32_t offset;
|
||||||
|
uint32_t vcpu;
|
||||||
|
/* OUT parameters. */
|
||||||
|
uint8_t link_bits;
|
||||||
|
uint8_t _pad[7];
|
||||||
|
};
|
||||||
|
typedef struct evtchn_init_control evtchn_init_control_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* EVTCHNOP_expand_array: add an additional page to the event array.
|
||||||
|
*/
|
||||||
|
struct evtchn_expand_array {
|
||||||
|
/* IN parameters. */
|
||||||
|
uint64_t array_gfn;
|
||||||
|
};
|
||||||
|
typedef struct evtchn_expand_array evtchn_expand_array_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* EVTCHNOP_set_priority: set the priority for an event channel.
|
||||||
|
*/
|
||||||
|
struct evtchn_set_priority {
|
||||||
|
/* IN parameters. */
|
||||||
|
uint32_t port;
|
||||||
|
uint32_t priority;
|
||||||
|
};
|
||||||
|
typedef struct evtchn_set_priority evtchn_set_priority_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ` enum neg_errnoval
|
||||||
|
* ` HYPERVISOR_event_channel_op_compat(struct evtchn_op *op)
|
||||||
|
* `
|
||||||
|
* Superceded by new event_channel_op() hypercall since 0x00030202.
|
||||||
|
*/
|
||||||
|
struct evtchn_op {
|
||||||
|
uint32_t cmd; /* enum event_channel_op */
|
||||||
|
union {
|
||||||
|
struct evtchn_alloc_unbound alloc_unbound;
|
||||||
|
struct evtchn_bind_interdomain bind_interdomain;
|
||||||
|
struct evtchn_bind_virq bind_virq;
|
||||||
|
struct evtchn_bind_pirq bind_pirq;
|
||||||
|
struct evtchn_bind_ipi bind_ipi;
|
||||||
|
struct evtchn_close close;
|
||||||
|
struct evtchn_send send;
|
||||||
|
struct evtchn_status status;
|
||||||
|
struct evtchn_bind_vcpu bind_vcpu;
|
||||||
|
struct evtchn_unmask unmask;
|
||||||
|
} u;
|
||||||
|
};
|
||||||
|
typedef struct evtchn_op evtchn_op_t;
|
||||||
|
DEFINE_XEN_GUEST_HANDLE(evtchn_op_t);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 2-level ABI
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define EVTCHN_2L_NR_CHANNELS (sizeof(xen_ulong_t) * sizeof(xen_ulong_t) * 64)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FIFO ABI
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Events may have priorities from 0 (highest) to 15 (lowest). */
|
||||||
|
#define EVTCHN_FIFO_PRIORITY_MAX 0
|
||||||
|
#define EVTCHN_FIFO_PRIORITY_DEFAULT 7
|
||||||
|
#define EVTCHN_FIFO_PRIORITY_MIN 15
|
||||||
|
|
||||||
|
#define EVTCHN_FIFO_MAX_QUEUES (EVTCHN_FIFO_PRIORITY_MIN + 1)
|
||||||
|
|
||||||
|
typedef uint32_t event_word_t;
|
||||||
|
|
||||||
|
#define EVTCHN_FIFO_PENDING 31
|
||||||
|
#define EVTCHN_FIFO_MASKED 30
|
||||||
|
#define EVTCHN_FIFO_LINKED 29
|
||||||
|
#define EVTCHN_FIFO_BUSY 28
|
||||||
|
|
||||||
|
#define EVTCHN_FIFO_LINK_BITS 17
|
||||||
|
#define EVTCHN_FIFO_LINK_MASK ((1 << EVTCHN_FIFO_LINK_BITS) - 1)
|
||||||
|
|
||||||
|
#define EVTCHN_FIFO_NR_CHANNELS (1 << EVTCHN_FIFO_LINK_BITS)
|
||||||
|
|
||||||
|
struct evtchn_fifo_control_block {
|
||||||
|
uint32_t ready;
|
||||||
|
uint32_t _rsvd;
|
||||||
|
uint32_t head[EVTCHN_FIFO_MAX_QUEUES];
|
||||||
|
};
|
||||||
|
typedef struct evtchn_fifo_control_block evtchn_fifo_control_block_t;
|
||||||
|
|
||||||
|
#endif /* __XEN_PUBLIC_EVENT_CHANNEL_H__ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local variables:
|
||||||
|
* mode: C
|
||||||
|
* c-file-style: "BSD"
|
||||||
|
* c-basic-offset: 4
|
||||||
|
* tab-width: 4
|
||||||
|
* indent-tabs-mode: nil
|
||||||
|
* End:
|
||||||
|
*/
|
662
include/xen/grant_table.h
Normal file
662
include/xen/grant_table.h
Normal file
|
@ -0,0 +1,662 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* grant_table.h
|
||||||
|
*
|
||||||
|
* Interface for granting foreign access to page frames, and receiving
|
||||||
|
* page-ownership transfers.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to
|
||||||
|
* deal in the Software without restriction, including without limitation the
|
||||||
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
* sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2004, K A Fraser
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __XEN_PUBLIC_GRANT_TABLE_H__
|
||||||
|
#define __XEN_PUBLIC_GRANT_TABLE_H__
|
||||||
|
|
||||||
|
#include "xen.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* `incontents 150 gnttab Grant Tables
|
||||||
|
*
|
||||||
|
* Xen's grant tables provide a generic mechanism to memory sharing
|
||||||
|
* between domains. This shared memory interface underpins the split
|
||||||
|
* device drivers for block and network IO.
|
||||||
|
*
|
||||||
|
* Each domain has its own grant table. This is a data structure that
|
||||||
|
* is shared with Xen; it allows the domain to tell Xen what kind of
|
||||||
|
* permissions other domains have on its pages. Entries in the grant
|
||||||
|
* table are identified by grant references. A grant reference is an
|
||||||
|
* integer, which indexes into the grant table. It acts as a
|
||||||
|
* capability which the grantee can use to perform operations on the
|
||||||
|
* granter’s memory.
|
||||||
|
*
|
||||||
|
* This capability-based system allows shared-memory communications
|
||||||
|
* between unprivileged domains. A grant reference also encapsulates
|
||||||
|
* the details of a shared page, removing the need for a domain to
|
||||||
|
* know the real machine address of a page it is sharing. This makes
|
||||||
|
* it possible to share memory correctly with domains running in
|
||||||
|
* fully virtualised memory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/***********************************
|
||||||
|
* GRANT TABLE REPRESENTATION
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Some rough guidelines on accessing and updating grant-table entries
|
||||||
|
* in a concurrency-safe manner. For more information, Linux contains a
|
||||||
|
* reference implementation for guest OSes (drivers/xen/grant_table.c, see
|
||||||
|
* http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=drivers/xen/grant-table.c;hb=HEAD
|
||||||
|
*
|
||||||
|
* NB. WMB is a no-op on current-generation x86 processors. However, a
|
||||||
|
* compiler barrier will still be required.
|
||||||
|
*
|
||||||
|
* Introducing a valid entry into the grant table:
|
||||||
|
* 1. Write ent->domid.
|
||||||
|
* 2. Write ent->frame:
|
||||||
|
* GTF_permit_access: Frame to which access is permitted.
|
||||||
|
* GTF_accept_transfer: Pseudo-phys frame slot being filled by new
|
||||||
|
* frame, or zero if none.
|
||||||
|
* 3. Write memory barrier (WMB).
|
||||||
|
* 4. Write ent->flags, inc. valid type.
|
||||||
|
*
|
||||||
|
* Invalidating an unused GTF_permit_access entry:
|
||||||
|
* 1. flags = ent->flags.
|
||||||
|
* 2. Observe that !(flags & (GTF_reading|GTF_writing)).
|
||||||
|
* 3. Check result of SMP-safe CMPXCHG(&ent->flags, flags, 0).
|
||||||
|
* NB. No need for WMB as reuse of entry is control-dependent on success of
|
||||||
|
* step 3, and all architectures guarantee ordering of ctrl-dep writes.
|
||||||
|
*
|
||||||
|
* Invalidating an in-use GTF_permit_access entry:
|
||||||
|
* This cannot be done directly. Request assistance from the domain controller
|
||||||
|
* which can set a timeout on the use of a grant entry and take necessary
|
||||||
|
* action. (NB. This is not yet implemented!).
|
||||||
|
*
|
||||||
|
* Invalidating an unused GTF_accept_transfer entry:
|
||||||
|
* 1. flags = ent->flags.
|
||||||
|
* 2. Observe that !(flags & GTF_transfer_committed). [*]
|
||||||
|
* 3. Check result of SMP-safe CMPXCHG(&ent->flags, flags, 0).
|
||||||
|
* NB. No need for WMB as reuse of entry is control-dependent on success of
|
||||||
|
* step 3, and all architectures guarantee ordering of ctrl-dep writes.
|
||||||
|
* [*] If GTF_transfer_committed is set then the grant entry is 'committed'.
|
||||||
|
* The guest must /not/ modify the grant entry until the address of the
|
||||||
|
* transferred frame is written. It is safe for the guest to spin waiting
|
||||||
|
* for this to occur (detect by observing GTF_transfer_completed in
|
||||||
|
* ent->flags).
|
||||||
|
*
|
||||||
|
* Invalidating a committed GTF_accept_transfer entry:
|
||||||
|
* 1. Wait for (ent->flags & GTF_transfer_completed).
|
||||||
|
*
|
||||||
|
* Changing a GTF_permit_access from writable to read-only:
|
||||||
|
* Use SMP-safe CMPXCHG to set GTF_readonly, while checking !GTF_writing.
|
||||||
|
*
|
||||||
|
* Changing a GTF_permit_access from read-only to writable:
|
||||||
|
* Use SMP-safe bit-setting instruction.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reference to a grant entry in a specified domain's grant table.
|
||||||
|
*/
|
||||||
|
typedef uint32_t grant_ref_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A grant table comprises a packed array of grant entries in one or more
|
||||||
|
* page frames shared between Xen and a guest.
|
||||||
|
* [XEN]: This field is written by Xen and read by the sharing guest.
|
||||||
|
* [GST]: This field is written by the guest and read by Xen.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Version 1 of the grant table entry structure is maintained purely
|
||||||
|
* for backwards compatibility. New guests should use version 2.
|
||||||
|
*/
|
||||||
|
#if __XEN_INTERFACE_VERSION__ < 0x0003020a
|
||||||
|
#define grant_entry_v1 grant_entry
|
||||||
|
#define grant_entry_v1_t grant_entry_t
|
||||||
|
#endif
|
||||||
|
struct grant_entry_v1 {
|
||||||
|
/* GTF_xxx: various type and flag information. [XEN,GST] */
|
||||||
|
uint16_t flags;
|
||||||
|
/* The domain being granted foreign privileges. [GST] */
|
||||||
|
domid_t domid;
|
||||||
|
/*
|
||||||
|
* GTF_permit_access: Frame that @domid is allowed to map and access. [GST]
|
||||||
|
* GTF_accept_transfer: Frame whose ownership transferred by @domid. [XEN]
|
||||||
|
*/
|
||||||
|
uint32_t frame;
|
||||||
|
};
|
||||||
|
typedef struct grant_entry_v1 grant_entry_v1_t;
|
||||||
|
|
||||||
|
/* The first few grant table entries will be preserved across grant table
|
||||||
|
* version changes and may be pre-populated at domain creation by tools.
|
||||||
|
*/
|
||||||
|
#define GNTTAB_NR_RESERVED_ENTRIES 8
|
||||||
|
#define GNTTAB_RESERVED_CONSOLE 0
|
||||||
|
#define GNTTAB_RESERVED_XENSTORE 1
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Type of grant entry.
|
||||||
|
* GTF_invalid: This grant entry grants no privileges.
|
||||||
|
* GTF_permit_access: Allow @domid to map/access @frame.
|
||||||
|
* GTF_accept_transfer: Allow @domid to transfer ownership of one page frame
|
||||||
|
* to this guest. Xen writes the page number to @frame.
|
||||||
|
* GTF_transitive: Allow @domid to transitively access a subrange of
|
||||||
|
* @trans_grant in @trans_domid. No mappings are allowed.
|
||||||
|
*/
|
||||||
|
#define GTF_invalid (0U<<0)
|
||||||
|
#define GTF_permit_access (1U<<0)
|
||||||
|
#define GTF_accept_transfer (2U<<0)
|
||||||
|
#define GTF_transitive (3U<<0)
|
||||||
|
#define GTF_type_mask (3U<<0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Subflags for GTF_permit_access.
|
||||||
|
* GTF_readonly: Restrict @domid to read-only mappings and accesses. [GST]
|
||||||
|
* GTF_reading: Grant entry is currently mapped for reading by @domid. [XEN]
|
||||||
|
* GTF_writing: Grant entry is currently mapped for writing by @domid. [XEN]
|
||||||
|
* GTF_PAT, GTF_PWT, GTF_PCD: (x86) cache attribute flags for the grant [GST]
|
||||||
|
* GTF_sub_page: Grant access to only a subrange of the page. @domid
|
||||||
|
* will only be allowed to copy from the grant, and not
|
||||||
|
* map it. [GST]
|
||||||
|
*/
|
||||||
|
#define _GTF_readonly (2)
|
||||||
|
#define GTF_readonly (1U<<_GTF_readonly)
|
||||||
|
#define _GTF_reading (3)
|
||||||
|
#define GTF_reading (1U<<_GTF_reading)
|
||||||
|
#define _GTF_writing (4)
|
||||||
|
#define GTF_writing (1U<<_GTF_writing)
|
||||||
|
#define _GTF_PWT (5)
|
||||||
|
#define GTF_PWT (1U<<_GTF_PWT)
|
||||||
|
#define _GTF_PCD (6)
|
||||||
|
#define GTF_PCD (1U<<_GTF_PCD)
|
||||||
|
#define _GTF_PAT (7)
|
||||||
|
#define GTF_PAT (1U<<_GTF_PAT)
|
||||||
|
#define _GTF_sub_page (8)
|
||||||
|
#define GTF_sub_page (1U<<_GTF_sub_page)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Subflags for GTF_accept_transfer:
|
||||||
|
* GTF_transfer_committed: Xen sets this flag to indicate that it is committed
|
||||||
|
* to transferring ownership of a page frame. When a guest sees this flag
|
||||||
|
* it must /not/ modify the grant entry until GTF_transfer_completed is
|
||||||
|
* set by Xen.
|
||||||
|
* GTF_transfer_completed: It is safe for the guest to spin-wait on this flag
|
||||||
|
* after reading GTF_transfer_committed. Xen will always write the frame
|
||||||
|
* address, followed by ORing this flag, in a timely manner.
|
||||||
|
*/
|
||||||
|
#define _GTF_transfer_committed (2)
|
||||||
|
#define GTF_transfer_committed (1U<<_GTF_transfer_committed)
|
||||||
|
#define _GTF_transfer_completed (3)
|
||||||
|
#define GTF_transfer_completed (1U<<_GTF_transfer_completed)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Version 2 grant table entries. These fulfil the same role as
|
||||||
|
* version 1 entries, but can represent more complicated operations.
|
||||||
|
* Any given domain will have either a version 1 or a version 2 table,
|
||||||
|
* and every entry in the table will be the same version.
|
||||||
|
*
|
||||||
|
* The interface by which domains use grant references does not depend
|
||||||
|
* on the grant table version in use by the other domain.
|
||||||
|
*/
|
||||||
|
#if __XEN_INTERFACE_VERSION__ >= 0x0003020a
|
||||||
|
/*
|
||||||
|
* Version 1 and version 2 grant entries share a common prefix. The
|
||||||
|
* fields of the prefix are documented as part of struct
|
||||||
|
* grant_entry_v1.
|
||||||
|
*/
|
||||||
|
struct grant_entry_header {
|
||||||
|
uint16_t flags;
|
||||||
|
domid_t domid;
|
||||||
|
};
|
||||||
|
typedef struct grant_entry_header grant_entry_header_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Version 2 of the grant entry structure.
|
||||||
|
*/
|
||||||
|
union grant_entry_v2 {
|
||||||
|
grant_entry_header_t hdr;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This member is used for V1-style full page grants, where either:
|
||||||
|
*
|
||||||
|
* -- hdr.type is GTF_accept_transfer, or
|
||||||
|
* -- hdr.type is GTF_permit_access and GTF_sub_page is not set.
|
||||||
|
*
|
||||||
|
* In that case, the frame field has the same semantics as the
|
||||||
|
* field of the same name in the V1 entry structure.
|
||||||
|
*/
|
||||||
|
struct {
|
||||||
|
grant_entry_header_t hdr;
|
||||||
|
uint32_t pad0;
|
||||||
|
uint64_t frame;
|
||||||
|
} full_page;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the grant type is GTF_grant_access and GTF_sub_page is set,
|
||||||
|
* @domid is allowed to access bytes [@page_off,@page_off+@length)
|
||||||
|
* in frame @frame.
|
||||||
|
*/
|
||||||
|
struct {
|
||||||
|
grant_entry_header_t hdr;
|
||||||
|
uint16_t page_off;
|
||||||
|
uint16_t length;
|
||||||
|
uint64_t frame;
|
||||||
|
} sub_page;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the grant is GTF_transitive, @domid is allowed to use the
|
||||||
|
* grant @gref in domain @trans_domid, as if it was the local
|
||||||
|
* domain. Obviously, the transitive access must be compatible
|
||||||
|
* with the original grant.
|
||||||
|
*
|
||||||
|
* The current version of Xen does not allow transitive grants
|
||||||
|
* to be mapped.
|
||||||
|
*/
|
||||||
|
struct {
|
||||||
|
grant_entry_header_t hdr;
|
||||||
|
domid_t trans_domid;
|
||||||
|
uint16_t pad0;
|
||||||
|
grant_ref_t gref;
|
||||||
|
} transitive;
|
||||||
|
|
||||||
|
uint32_t __spacer[4]; /* Pad to a power of two */
|
||||||
|
};
|
||||||
|
typedef union grant_entry_v2 grant_entry_v2_t;
|
||||||
|
|
||||||
|
typedef uint16_t grant_status_t;
|
||||||
|
|
||||||
|
#endif /* __XEN_INTERFACE_VERSION__ */
|
||||||
|
|
||||||
|
/***********************************
|
||||||
|
* GRANT TABLE QUERIES AND USES
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ` enum neg_errnoval
|
||||||
|
* ` HYPERVISOR_grant_table_op(enum grant_table_op cmd,
|
||||||
|
* ` void *args,
|
||||||
|
* ` unsigned int count)
|
||||||
|
* `
|
||||||
|
*
|
||||||
|
* @args points to an array of a per-command data structure. The array
|
||||||
|
* has @count members
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ` enum grant_table_op { // GNTTABOP_* => struct gnttab_* */
|
||||||
|
#define GNTTABOP_map_grant_ref 0
|
||||||
|
#define GNTTABOP_unmap_grant_ref 1
|
||||||
|
#define GNTTABOP_setup_table 2
|
||||||
|
#define GNTTABOP_dump_table 3
|
||||||
|
#define GNTTABOP_transfer 4
|
||||||
|
#define GNTTABOP_copy 5
|
||||||
|
#define GNTTABOP_query_size 6
|
||||||
|
#define GNTTABOP_unmap_and_replace 7
|
||||||
|
#if __XEN_INTERFACE_VERSION__ >= 0x0003020a
|
||||||
|
#define GNTTABOP_set_version 8
|
||||||
|
#define GNTTABOP_get_status_frames 9
|
||||||
|
#define GNTTABOP_get_version 10
|
||||||
|
#define GNTTABOP_swap_grant_ref 11
|
||||||
|
#endif /* __XEN_INTERFACE_VERSION__ */
|
||||||
|
/* ` } */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handle to track a mapping created via a grant reference.
|
||||||
|
*/
|
||||||
|
typedef uint32_t grant_handle_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GNTTABOP_map_grant_ref: Map the grant entry (<dom>,<ref>) for access
|
||||||
|
* by devices and/or host CPUs. If successful, <handle> is a tracking number
|
||||||
|
* that must be presented later to destroy the mapping(s). On error, <handle>
|
||||||
|
* is a negative status code.
|
||||||
|
* NOTES:
|
||||||
|
* 1. If GNTMAP_device_map is specified then <dev_bus_addr> is the address
|
||||||
|
* via which I/O devices may access the granted frame.
|
||||||
|
* 2. If GNTMAP_host_map is specified then a mapping will be added at
|
||||||
|
* either a host virtual address in the current address space, or at
|
||||||
|
* a PTE at the specified machine address. The type of mapping to
|
||||||
|
* perform is selected through the GNTMAP_contains_pte flag, and the
|
||||||
|
* address is specified in <host_addr>.
|
||||||
|
* 3. Mappings should only be destroyed via GNTTABOP_unmap_grant_ref. If a
|
||||||
|
* host mapping is destroyed by other means then it is *NOT* guaranteed
|
||||||
|
* to be accounted to the correct grant reference!
|
||||||
|
*/
|
||||||
|
struct gnttab_map_grant_ref {
|
||||||
|
/* IN parameters. */
|
||||||
|
uint64_t host_addr;
|
||||||
|
uint32_t flags; /* GNTMAP_* */
|
||||||
|
grant_ref_t ref;
|
||||||
|
domid_t dom;
|
||||||
|
/* OUT parameters. */
|
||||||
|
int16_t status; /* => enum grant_status */
|
||||||
|
grant_handle_t handle;
|
||||||
|
uint64_t dev_bus_addr;
|
||||||
|
};
|
||||||
|
typedef struct gnttab_map_grant_ref gnttab_map_grant_ref_t;
|
||||||
|
DEFINE_XEN_GUEST_HANDLE(gnttab_map_grant_ref_t);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GNTTABOP_unmap_grant_ref: Destroy one or more grant-reference mappings
|
||||||
|
* tracked by <handle>. If <host_addr> or <dev_bus_addr> is zero, that
|
||||||
|
* field is ignored. If non-zero, they must refer to a device/host mapping
|
||||||
|
* that is tracked by <handle>
|
||||||
|
* NOTES:
|
||||||
|
* 1. The call may fail in an undefined manner if either mapping is not
|
||||||
|
* tracked by <handle>.
|
||||||
|
* 3. After executing a batch of unmaps, it is guaranteed that no stale
|
||||||
|
* mappings will remain in the device or host TLBs.
|
||||||
|
*/
|
||||||
|
struct gnttab_unmap_grant_ref {
|
||||||
|
/* IN parameters. */
|
||||||
|
uint64_t host_addr;
|
||||||
|
uint64_t dev_bus_addr;
|
||||||
|
grant_handle_t handle;
|
||||||
|
/* OUT parameters. */
|
||||||
|
int16_t status; /* => enum grant_status */
|
||||||
|
};
|
||||||
|
typedef struct gnttab_unmap_grant_ref gnttab_unmap_grant_ref_t;
|
||||||
|
DEFINE_XEN_GUEST_HANDLE(gnttab_unmap_grant_ref_t);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GNTTABOP_setup_table: Set up a grant table for <dom> comprising at least
|
||||||
|
* <nr_frames> pages. The frame addresses are written to the <frame_list>.
|
||||||
|
* Only <nr_frames> addresses are written, even if the table is larger.
|
||||||
|
* NOTES:
|
||||||
|
* 1. <dom> may be specified as DOMID_SELF.
|
||||||
|
* 2. Only a sufficiently-privileged domain may specify <dom> != DOMID_SELF.
|
||||||
|
* 3. Xen may not support more than a single grant-table page per domain.
|
||||||
|
*/
|
||||||
|
struct gnttab_setup_table {
|
||||||
|
/* IN parameters. */
|
||||||
|
domid_t dom;
|
||||||
|
uint32_t nr_frames;
|
||||||
|
/* OUT parameters. */
|
||||||
|
int16_t status; /* => enum grant_status */
|
||||||
|
#if __XEN_INTERFACE_VERSION__ < 0x00040300
|
||||||
|
XEN_GUEST_HANDLE(ulong) frame_list;
|
||||||
|
#else
|
||||||
|
XEN_GUEST_HANDLE(xen_pfn_t) frame_list;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
typedef struct gnttab_setup_table gnttab_setup_table_t;
|
||||||
|
DEFINE_XEN_GUEST_HANDLE(gnttab_setup_table_t);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GNTTABOP_dump_table: Dump the contents of the grant table to the
|
||||||
|
* xen console. Debugging use only.
|
||||||
|
*/
|
||||||
|
struct gnttab_dump_table {
|
||||||
|
/* IN parameters. */
|
||||||
|
domid_t dom;
|
||||||
|
/* OUT parameters. */
|
||||||
|
int16_t status; /* => enum grant_status */
|
||||||
|
};
|
||||||
|
typedef struct gnttab_dump_table gnttab_dump_table_t;
|
||||||
|
DEFINE_XEN_GUEST_HANDLE(gnttab_dump_table_t);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GNTTABOP_transfer_grant_ref: Transfer <frame> to a foreign domain. The
|
||||||
|
* foreign domain has previously registered its interest in the transfer via
|
||||||
|
* <domid, ref>.
|
||||||
|
*
|
||||||
|
* Note that, even if the transfer fails, the specified page no longer belongs
|
||||||
|
* to the calling domain *unless* the error is GNTST_bad_page.
|
||||||
|
*/
|
||||||
|
struct gnttab_transfer {
|
||||||
|
/* IN parameters. */
|
||||||
|
xen_pfn_t mfn;
|
||||||
|
domid_t domid;
|
||||||
|
grant_ref_t ref;
|
||||||
|
/* OUT parameters. */
|
||||||
|
int16_t status;
|
||||||
|
};
|
||||||
|
typedef struct gnttab_transfer gnttab_transfer_t;
|
||||||
|
DEFINE_XEN_GUEST_HANDLE(gnttab_transfer_t);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GNTTABOP_copy: Hypervisor based copy
|
||||||
|
* source and destinations can be eithers MFNs or, for foreign domains,
|
||||||
|
* grant references. the foreign domain has to grant read/write access
|
||||||
|
* in its grant table.
|
||||||
|
*
|
||||||
|
* The flags specify what type source and destinations are (either MFN
|
||||||
|
* or grant reference).
|
||||||
|
*
|
||||||
|
* Note that this can also be used to copy data between two domains
|
||||||
|
* via a third party if the source and destination domains had previously
|
||||||
|
* grant appropriate access to their pages to the third party.
|
||||||
|
*
|
||||||
|
* source_offset specifies an offset in the source frame, dest_offset
|
||||||
|
* the offset in the target frame and len specifies the number of
|
||||||
|
* bytes to be copied.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define _GNTCOPY_source_gref (0)
|
||||||
|
#define GNTCOPY_source_gref (1<<_GNTCOPY_source_gref)
|
||||||
|
#define _GNTCOPY_dest_gref (1)
|
||||||
|
#define GNTCOPY_dest_gref (1<<_GNTCOPY_dest_gref)
|
||||||
|
|
||||||
|
struct gnttab_copy {
|
||||||
|
/* IN parameters. */
|
||||||
|
struct {
|
||||||
|
union {
|
||||||
|
grant_ref_t ref;
|
||||||
|
xen_pfn_t gmfn;
|
||||||
|
} u;
|
||||||
|
domid_t domid;
|
||||||
|
uint16_t offset;
|
||||||
|
} source, dest;
|
||||||
|
uint16_t len;
|
||||||
|
uint16_t flags; /* GNTCOPY_* */
|
||||||
|
/* OUT parameters. */
|
||||||
|
int16_t status;
|
||||||
|
};
|
||||||
|
typedef struct gnttab_copy gnttab_copy_t;
|
||||||
|
DEFINE_XEN_GUEST_HANDLE(gnttab_copy_t);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GNTTABOP_query_size: Query the current and maximum sizes of the shared
|
||||||
|
* grant table.
|
||||||
|
* NOTES:
|
||||||
|
* 1. <dom> may be specified as DOMID_SELF.
|
||||||
|
* 2. Only a sufficiently-privileged domain may specify <dom> != DOMID_SELF.
|
||||||
|
*/
|
||||||
|
struct gnttab_query_size {
|
||||||
|
/* IN parameters. */
|
||||||
|
domid_t dom;
|
||||||
|
/* OUT parameters. */
|
||||||
|
uint32_t nr_frames;
|
||||||
|
uint32_t max_nr_frames;
|
||||||
|
int16_t status; /* => enum grant_status */
|
||||||
|
};
|
||||||
|
typedef struct gnttab_query_size gnttab_query_size_t;
|
||||||
|
DEFINE_XEN_GUEST_HANDLE(gnttab_query_size_t);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GNTTABOP_unmap_and_replace: Destroy one or more grant-reference mappings
|
||||||
|
* tracked by <handle> but atomically replace the page table entry with one
|
||||||
|
* pointing to the machine address under <new_addr>. <new_addr> will be
|
||||||
|
* redirected to the null entry.
|
||||||
|
* NOTES:
|
||||||
|
* 1. The call may fail in an undefined manner if either mapping is not
|
||||||
|
* tracked by <handle>.
|
||||||
|
* 2. After executing a batch of unmaps, it is guaranteed that no stale
|
||||||
|
* mappings will remain in the device or host TLBs.
|
||||||
|
*/
|
||||||
|
struct gnttab_unmap_and_replace {
|
||||||
|
/* IN parameters. */
|
||||||
|
uint64_t host_addr;
|
||||||
|
uint64_t new_addr;
|
||||||
|
grant_handle_t handle;
|
||||||
|
/* OUT parameters. */
|
||||||
|
int16_t status; /* => enum grant_status */
|
||||||
|
};
|
||||||
|
typedef struct gnttab_unmap_and_replace gnttab_unmap_and_replace_t;
|
||||||
|
DEFINE_XEN_GUEST_HANDLE(gnttab_unmap_and_replace_t);
|
||||||
|
|
||||||
|
#if __XEN_INTERFACE_VERSION__ >= 0x0003020a
|
||||||
|
/*
|
||||||
|
* GNTTABOP_set_version: Request a particular version of the grant
|
||||||
|
* table shared table structure. This operation can only be performed
|
||||||
|
* once in any given domain. It must be performed before any grants
|
||||||
|
* are activated; otherwise, the domain will be stuck with version 1.
|
||||||
|
* The only defined versions are 1 and 2.
|
||||||
|
*/
|
||||||
|
struct gnttab_set_version {
|
||||||
|
/* IN/OUT parameters */
|
||||||
|
uint32_t version;
|
||||||
|
};
|
||||||
|
typedef struct gnttab_set_version gnttab_set_version_t;
|
||||||
|
DEFINE_XEN_GUEST_HANDLE(gnttab_set_version_t);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GNTTABOP_get_status_frames: Get the list of frames used to store grant
|
||||||
|
* status for <dom>. In grant format version 2, the status is separated
|
||||||
|
* from the other shared grant fields to allow more efficient synchronization
|
||||||
|
* using barriers instead of atomic cmpexch operations.
|
||||||
|
* <nr_frames> specify the size of vector <frame_list>.
|
||||||
|
* The frame addresses are returned in the <frame_list>.
|
||||||
|
* Only <nr_frames> addresses are returned, even if the table is larger.
|
||||||
|
* NOTES:
|
||||||
|
* 1. <dom> may be specified as DOMID_SELF.
|
||||||
|
* 2. Only a sufficiently-privileged domain may specify <dom> != DOMID_SELF.
|
||||||
|
*/
|
||||||
|
struct gnttab_get_status_frames {
|
||||||
|
/* IN parameters. */
|
||||||
|
uint32_t nr_frames;
|
||||||
|
domid_t dom;
|
||||||
|
/* OUT parameters. */
|
||||||
|
int16_t status; /* => enum grant_status */
|
||||||
|
XEN_GUEST_HANDLE(uint64_t) frame_list;
|
||||||
|
};
|
||||||
|
typedef struct gnttab_get_status_frames gnttab_get_status_frames_t;
|
||||||
|
DEFINE_XEN_GUEST_HANDLE(gnttab_get_status_frames_t);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GNTTABOP_get_version: Get the grant table version which is in
|
||||||
|
* effect for domain <dom>.
|
||||||
|
*/
|
||||||
|
struct gnttab_get_version {
|
||||||
|
/* IN parameters */
|
||||||
|
domid_t dom;
|
||||||
|
uint16_t pad;
|
||||||
|
/* OUT parameters */
|
||||||
|
uint32_t version;
|
||||||
|
};
|
||||||
|
typedef struct gnttab_get_version gnttab_get_version_t;
|
||||||
|
DEFINE_XEN_GUEST_HANDLE(gnttab_get_version_t);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GNTTABOP_swap_grant_ref: Swap the contents of two grant entries.
|
||||||
|
*/
|
||||||
|
struct gnttab_swap_grant_ref {
|
||||||
|
/* IN parameters */
|
||||||
|
grant_ref_t ref_a;
|
||||||
|
grant_ref_t ref_b;
|
||||||
|
/* OUT parameters */
|
||||||
|
int16_t status; /* => enum grant_status */
|
||||||
|
};
|
||||||
|
typedef struct gnttab_swap_grant_ref gnttab_swap_grant_ref_t;
|
||||||
|
DEFINE_XEN_GUEST_HANDLE(gnttab_swap_grant_ref_t);
|
||||||
|
|
||||||
|
#endif /* __XEN_INTERFACE_VERSION__ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Bitfield values for gnttab_map_grant_ref.flags.
|
||||||
|
*/
|
||||||
|
/* Map the grant entry for access by I/O devices. */
|
||||||
|
#define _GNTMAP_device_map (0)
|
||||||
|
#define GNTMAP_device_map (1<<_GNTMAP_device_map)
|
||||||
|
/* Map the grant entry for access by host CPUs. */
|
||||||
|
#define _GNTMAP_host_map (1)
|
||||||
|
#define GNTMAP_host_map (1<<_GNTMAP_host_map)
|
||||||
|
/* Accesses to the granted frame will be restricted to read-only access. */
|
||||||
|
#define _GNTMAP_readonly (2)
|
||||||
|
#define GNTMAP_readonly (1<<_GNTMAP_readonly)
|
||||||
|
/*
|
||||||
|
* GNTMAP_host_map subflag:
|
||||||
|
* 0 => The host mapping is usable only by the guest OS.
|
||||||
|
* 1 => The host mapping is usable by guest OS + current application.
|
||||||
|
*/
|
||||||
|
#define _GNTMAP_application_map (3)
|
||||||
|
#define GNTMAP_application_map (1<<_GNTMAP_application_map)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GNTMAP_contains_pte subflag:
|
||||||
|
* 0 => This map request contains a host virtual address.
|
||||||
|
* 1 => This map request contains the machine addess of the PTE to update.
|
||||||
|
*/
|
||||||
|
#define _GNTMAP_contains_pte (4)
|
||||||
|
#define GNTMAP_contains_pte (1<<_GNTMAP_contains_pte)
|
||||||
|
|
||||||
|
#define _GNTMAP_can_fail (5)
|
||||||
|
#define GNTMAP_can_fail (1<<_GNTMAP_can_fail)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Bits to be placed in guest kernel available PTE bits (architecture
|
||||||
|
* dependent; only supported when XENFEAT_gnttab_map_avail_bits is set).
|
||||||
|
*/
|
||||||
|
#define _GNTMAP_guest_avail0 (16)
|
||||||
|
#define GNTMAP_guest_avail_mask ((uint32_t)~0 << _GNTMAP_guest_avail0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Values for error status returns. All errors are -ve.
|
||||||
|
*/
|
||||||
|
/* ` enum grant_status { */
|
||||||
|
#define GNTST_okay (0) /* Normal return. */
|
||||||
|
#define GNTST_general_error (-1) /* General undefined error. */
|
||||||
|
#define GNTST_bad_domain (-2) /* Unrecognsed domain id. */
|
||||||
|
#define GNTST_bad_gntref (-3) /* Unrecognised or inappropriate gntref. */
|
||||||
|
#define GNTST_bad_handle (-4) /* Unrecognised or inappropriate handle. */
|
||||||
|
#define GNTST_bad_virt_addr (-5) /* Inappropriate virtual address to map. */
|
||||||
|
#define GNTST_bad_dev_addr (-6) /* Inappropriate device address to unmap.*/
|
||||||
|
#define GNTST_no_device_space (-7) /* Out of space in I/O MMU. */
|
||||||
|
#define GNTST_permission_denied (-8) /* Not enough privilege for operation. */
|
||||||
|
#define GNTST_bad_page (-9) /* Specified page was invalid for op. */
|
||||||
|
#define GNTST_bad_copy_arg (-10) /* copy arguments cross page boundary. */
|
||||||
|
#define GNTST_address_too_big (-11) /* transfer page address too large. */
|
||||||
|
#define GNTST_eagain (-12) /* Operation not done; try again. */
|
||||||
|
/* ` } */
|
||||||
|
|
||||||
|
#define GNTTABOP_error_msgs { \
|
||||||
|
"okay", \
|
||||||
|
"undefined error", \
|
||||||
|
"unrecognised domain id", \
|
||||||
|
"invalid grant reference", \
|
||||||
|
"invalid mapping handle", \
|
||||||
|
"invalid virtual address", \
|
||||||
|
"invalid device address", \
|
||||||
|
"no spare translation slot in the I/O MMU", \
|
||||||
|
"permission denied", \
|
||||||
|
"bad page", \
|
||||||
|
"copy arguments cross page boundary", \
|
||||||
|
"page address size too large", \
|
||||||
|
"operation not done; try again" \
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __XEN_PUBLIC_GRANT_TABLE_H__ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local variables:
|
||||||
|
* mode: C
|
||||||
|
* c-file-style: "BSD"
|
||||||
|
* c-basic-offset: 4
|
||||||
|
* tab-width: 4
|
||||||
|
* indent-tabs-mode: nil
|
||||||
|
* End:
|
||||||
|
*/
|
608
include/xen/io/blkif.h
Normal file
608
include/xen/io/blkif.h
Normal file
|
@ -0,0 +1,608 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* blkif.h
|
||||||
|
*
|
||||||
|
* Unified block-device I/O interface for Xen guest OSes.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to
|
||||||
|
* deal in the Software without restriction, including without limitation the
|
||||||
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
* sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2003-2004, Keir Fraser
|
||||||
|
* Copyright (c) 2012, Spectra Logic Corporation
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __XEN_PUBLIC_IO_BLKIF_H__
|
||||||
|
#define __XEN_PUBLIC_IO_BLKIF_H__
|
||||||
|
|
||||||
|
#include "ring.h"
|
||||||
|
#include "../grant_table.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Front->back notifications: When enqueuing a new request, sending a
|
||||||
|
* notification can be made conditional on req_event (i.e., the generic
|
||||||
|
* hold-off mechanism provided by the ring macros). Backends must set
|
||||||
|
* req_event appropriately (e.g., using RING_FINAL_CHECK_FOR_REQUESTS()).
|
||||||
|
*
|
||||||
|
* Back->front notifications: When enqueuing a new response, sending a
|
||||||
|
* notification can be made conditional on rsp_event (i.e., the generic
|
||||||
|
* hold-off mechanism provided by the ring macros). Frontends must set
|
||||||
|
* rsp_event appropriately (e.g., using RING_FINAL_CHECK_FOR_RESPONSES()).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef blkif_vdev_t
|
||||||
|
#define blkif_vdev_t uint16_t
|
||||||
|
#endif
|
||||||
|
#define blkif_sector_t uint64_t
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Feature and Parameter Negotiation
|
||||||
|
* =================================
|
||||||
|
* The two halves of a Xen block driver utilize nodes within the XenStore to
|
||||||
|
* communicate capabilities and to negotiate operating parameters. This
|
||||||
|
* section enumerates these nodes which reside in the respective front and
|
||||||
|
* backend portions of the XenStore, following the XenBus convention.
|
||||||
|
*
|
||||||
|
* All data in the XenStore is stored as strings. Nodes specifying numeric
|
||||||
|
* values are encoded in decimal. Integer value ranges listed below are
|
||||||
|
* expressed as fixed sized integer types capable of storing the conversion
|
||||||
|
* of a properly formated node string, without loss of information.
|
||||||
|
*
|
||||||
|
* Any specified default value is in effect if the corresponding XenBus node
|
||||||
|
* is not present in the XenStore.
|
||||||
|
*
|
||||||
|
* XenStore nodes in sections marked "PRIVATE" are solely for use by the
|
||||||
|
* driver side whose XenBus tree contains them.
|
||||||
|
*
|
||||||
|
* XenStore nodes marked "DEPRECATED" in their notes section should only be
|
||||||
|
* used to provide interoperability with legacy implementations.
|
||||||
|
*
|
||||||
|
* See the XenBus state transition diagram below for details on when XenBus
|
||||||
|
* nodes must be published and when they can be queried.
|
||||||
|
*
|
||||||
|
*****************************************************************************
|
||||||
|
* Backend XenBus Nodes
|
||||||
|
*****************************************************************************
|
||||||
|
*
|
||||||
|
*------------------ Backend Device Identification (PRIVATE) ------------------
|
||||||
|
*
|
||||||
|
* mode
|
||||||
|
* Values: "r" (read only), "w" (writable)
|
||||||
|
*
|
||||||
|
* The read or write access permissions to the backing store to be
|
||||||
|
* granted to the frontend.
|
||||||
|
*
|
||||||
|
* params
|
||||||
|
* Values: string
|
||||||
|
*
|
||||||
|
* A free formatted string providing sufficient information for the
|
||||||
|
* backend driver to open the backing device. (e.g. the path to the
|
||||||
|
* file or block device representing the backing store.)
|
||||||
|
*
|
||||||
|
* type
|
||||||
|
* Values: "file", "phy", "tap"
|
||||||
|
*
|
||||||
|
* The type of the backing device/object.
|
||||||
|
*
|
||||||
|
*--------------------------------- Features ---------------------------------
|
||||||
|
*
|
||||||
|
* feature-barrier
|
||||||
|
* Values: 0/1 (boolean)
|
||||||
|
* Default Value: 0
|
||||||
|
*
|
||||||
|
* A value of "1" indicates that the backend can process requests
|
||||||
|
* containing the BLKIF_OP_WRITE_BARRIER request opcode. Requests
|
||||||
|
* of this type may still be returned at any time with the
|
||||||
|
* BLKIF_RSP_EOPNOTSUPP result code.
|
||||||
|
*
|
||||||
|
* feature-flush-cache
|
||||||
|
* Values: 0/1 (boolean)
|
||||||
|
* Default Value: 0
|
||||||
|
*
|
||||||
|
* A value of "1" indicates that the backend can process requests
|
||||||
|
* containing the BLKIF_OP_FLUSH_DISKCACHE request opcode. Requests
|
||||||
|
* of this type may still be returned at any time with the
|
||||||
|
* BLKIF_RSP_EOPNOTSUPP result code.
|
||||||
|
*
|
||||||
|
* feature-discard
|
||||||
|
* Values: 0/1 (boolean)
|
||||||
|
* Default Value: 0
|
||||||
|
*
|
||||||
|
* A value of "1" indicates that the backend can process requests
|
||||||
|
* containing the BLKIF_OP_DISCARD request opcode. Requests
|
||||||
|
* of this type may still be returned at any time with the
|
||||||
|
* BLKIF_RSP_EOPNOTSUPP result code.
|
||||||
|
*
|
||||||
|
* feature-persistent
|
||||||
|
* Values: 0/1 (boolean)
|
||||||
|
* Default Value: 0
|
||||||
|
* Notes: 7
|
||||||
|
*
|
||||||
|
* A value of "1" indicates that the backend can keep the grants used
|
||||||
|
* by the frontend driver mapped, so the same set of grants should be
|
||||||
|
* used in all transactions. The maximum number of grants the backend
|
||||||
|
* can map persistently depends on the implementation, but ideally it
|
||||||
|
* should be RING_SIZE * BLKIF_MAX_SEGMENTS_PER_REQUEST. Using this
|
||||||
|
* feature the backend doesn't need to unmap each grant, preventing
|
||||||
|
* costly TLB flushes. The backend driver should only map grants
|
||||||
|
* persistently if the frontend supports it. If a backend driver chooses
|
||||||
|
* to use the persistent protocol when the frontend doesn't support it,
|
||||||
|
* it will probably hit the maximum number of persistently mapped grants
|
||||||
|
* (due to the fact that the frontend won't be reusing the same grants),
|
||||||
|
* and fall back to non-persistent mode. Backend implementations may
|
||||||
|
* shrink or expand the number of persistently mapped grants without
|
||||||
|
* notifying the frontend depending on memory constraints (this might
|
||||||
|
* cause a performance degradation).
|
||||||
|
*
|
||||||
|
* If a backend driver wants to limit the maximum number of persistently
|
||||||
|
* mapped grants to a value less than RING_SIZE *
|
||||||
|
* BLKIF_MAX_SEGMENTS_PER_REQUEST a LRU strategy should be used to
|
||||||
|
* discard the grants that are less commonly used. Using a LRU in the
|
||||||
|
* backend driver paired with a LIFO queue in the frontend will
|
||||||
|
* allow us to have better performance in this scenario.
|
||||||
|
*
|
||||||
|
*----------------------- Request Transport Parameters ------------------------
|
||||||
|
*
|
||||||
|
* max-ring-page-order
|
||||||
|
* Values: <uint32_t>
|
||||||
|
* Default Value: 0
|
||||||
|
* Notes: 1, 3
|
||||||
|
*
|
||||||
|
* The maximum supported size of the request ring buffer in units of
|
||||||
|
* lb(machine pages). (e.g. 0 == 1 page, 1 = 2 pages, 2 == 4 pages,
|
||||||
|
* etc.).
|
||||||
|
*
|
||||||
|
* max-ring-pages
|
||||||
|
* Values: <uint32_t>
|
||||||
|
* Default Value: 1
|
||||||
|
* Notes: DEPRECATED, 2, 3
|
||||||
|
*
|
||||||
|
* The maximum supported size of the request ring buffer in units of
|
||||||
|
* machine pages. The value must be a power of 2.
|
||||||
|
*
|
||||||
|
*------------------------- Backend Device Properties -------------------------
|
||||||
|
*
|
||||||
|
* discard-alignment
|
||||||
|
* Values: <uint32_t>
|
||||||
|
* Default Value: 0
|
||||||
|
* Notes: 4, 5
|
||||||
|
*
|
||||||
|
* The offset, in bytes from the beginning of the virtual block device,
|
||||||
|
* to the first, addressable, discard extent on the underlying device.
|
||||||
|
*
|
||||||
|
* discard-granularity
|
||||||
|
* Values: <uint32_t>
|
||||||
|
* Default Value: <"sector-size">
|
||||||
|
* Notes: 4
|
||||||
|
*
|
||||||
|
* The size, in bytes, of the individually addressable discard extents
|
||||||
|
* of the underlying device.
|
||||||
|
*
|
||||||
|
* discard-secure
|
||||||
|
* Values: 0/1 (boolean)
|
||||||
|
* Default Value: 0
|
||||||
|
* Notes: 10
|
||||||
|
*
|
||||||
|
* A value of "1" indicates that the backend can process BLKIF_OP_DISCARD
|
||||||
|
* requests with the BLKIF_DISCARD_SECURE flag set.
|
||||||
|
*
|
||||||
|
* info
|
||||||
|
* Values: <uint32_t> (bitmap)
|
||||||
|
*
|
||||||
|
* A collection of bit flags describing attributes of the backing
|
||||||
|
* device. The VDISK_* macros define the meaning of each bit
|
||||||
|
* location.
|
||||||
|
*
|
||||||
|
* sector-size
|
||||||
|
* Values: <uint32_t>
|
||||||
|
*
|
||||||
|
* The logical sector size, in bytes, of the backend device.
|
||||||
|
*
|
||||||
|
* physical-sector-size
|
||||||
|
* Values: <uint32_t>
|
||||||
|
*
|
||||||
|
* The physical sector size, in bytes, of the backend device.
|
||||||
|
*
|
||||||
|
* sectors
|
||||||
|
* Values: <uint64_t>
|
||||||
|
*
|
||||||
|
* The size of the backend device, expressed in units of its logical
|
||||||
|
* sector size ("sector-size").
|
||||||
|
*
|
||||||
|
*****************************************************************************
|
||||||
|
* Frontend XenBus Nodes
|
||||||
|
*****************************************************************************
|
||||||
|
*
|
||||||
|
*----------------------- Request Transport Parameters -----------------------
|
||||||
|
*
|
||||||
|
* event-channel
|
||||||
|
* Values: <uint32_t>
|
||||||
|
*
|
||||||
|
* The identifier of the Xen event channel used to signal activity
|
||||||
|
* in the ring buffer.
|
||||||
|
*
|
||||||
|
* ring-ref
|
||||||
|
* Values: <uint32_t>
|
||||||
|
* Notes: 6
|
||||||
|
*
|
||||||
|
* The Xen grant reference granting permission for the backend to map
|
||||||
|
* the sole page in a single page sized ring buffer.
|
||||||
|
*
|
||||||
|
* ring-ref%u
|
||||||
|
* Values: <uint32_t>
|
||||||
|
* Notes: 6
|
||||||
|
*
|
||||||
|
* For a frontend providing a multi-page ring, a "number of ring pages"
|
||||||
|
* sized list of nodes, each containing a Xen grant reference granting
|
||||||
|
* permission for the backend to map the page of the ring located
|
||||||
|
* at page index "%u". Page indexes are zero based.
|
||||||
|
*
|
||||||
|
* protocol
|
||||||
|
* Values: string (XEN_IO_PROTO_ABI_*)
|
||||||
|
* Default Value: XEN_IO_PROTO_ABI_NATIVE
|
||||||
|
*
|
||||||
|
* The machine ABI rules governing the format of all ring request and
|
||||||
|
* response structures.
|
||||||
|
*
|
||||||
|
* ring-page-order
|
||||||
|
* Values: <uint32_t>
|
||||||
|
* Default Value: 0
|
||||||
|
* Maximum Value: MAX(ffs(max-ring-pages) - 1, max-ring-page-order)
|
||||||
|
* Notes: 1, 3
|
||||||
|
*
|
||||||
|
* The size of the frontend allocated request ring buffer in units
|
||||||
|
* of lb(machine pages). (e.g. 0 == 1 page, 1 = 2 pages, 2 == 4 pages,
|
||||||
|
* etc.).
|
||||||
|
*
|
||||||
|
* num-ring-pages
|
||||||
|
* Values: <uint32_t>
|
||||||
|
* Default Value: 1
|
||||||
|
* Maximum Value: MAX(max-ring-pages,(0x1 << max-ring-page-order))
|
||||||
|
* Notes: DEPRECATED, 2, 3
|
||||||
|
*
|
||||||
|
* The size of the frontend allocated request ring buffer in units of
|
||||||
|
* machine pages. The value must be a power of 2.
|
||||||
|
*
|
||||||
|
* feature-persistent
|
||||||
|
* Values: 0/1 (boolean)
|
||||||
|
* Default Value: 0
|
||||||
|
* Notes: 7, 8, 9
|
||||||
|
*
|
||||||
|
* A value of "1" indicates that the frontend will reuse the same grants
|
||||||
|
* for all transactions, allowing the backend to map them with write
|
||||||
|
* access (even when it should be read-only). If the frontend hits the
|
||||||
|
* maximum number of allowed persistently mapped grants, it can fallback
|
||||||
|
* to non persistent mode. This will cause a performance degradation,
|
||||||
|
* since the the backend driver will still try to map those grants
|
||||||
|
* persistently. Since the persistent grants protocol is compatible with
|
||||||
|
* the previous protocol, a frontend driver can choose to work in
|
||||||
|
* persistent mode even when the backend doesn't support it.
|
||||||
|
*
|
||||||
|
* It is recommended that the frontend driver stores the persistently
|
||||||
|
* mapped grants in a LIFO queue, so a subset of all persistently mapped
|
||||||
|
* grants gets used commonly. This is done in case the backend driver
|
||||||
|
* decides to limit the maximum number of persistently mapped grants
|
||||||
|
* to a value less than RING_SIZE * BLKIF_MAX_SEGMENTS_PER_REQUEST.
|
||||||
|
*
|
||||||
|
*------------------------- Virtual Device Properties -------------------------
|
||||||
|
*
|
||||||
|
* device-type
|
||||||
|
* Values: "disk", "cdrom", "floppy", etc.
|
||||||
|
*
|
||||||
|
* virtual-device
|
||||||
|
* Values: <uint32_t>
|
||||||
|
*
|
||||||
|
* A value indicating the physical device to virtualize within the
|
||||||
|
* frontend's domain. (e.g. "The first ATA disk", "The third SCSI
|
||||||
|
* disk", etc.)
|
||||||
|
*
|
||||||
|
* See docs/misc/vbd-interface.txt for details on the format of this
|
||||||
|
* value.
|
||||||
|
*
|
||||||
|
* Notes
|
||||||
|
* -----
|
||||||
|
* (1) Multi-page ring buffer scheme first developed in the Citrix XenServer
|
||||||
|
* PV drivers.
|
||||||
|
* (2) Multi-page ring buffer scheme first used in some RedHat distributions
|
||||||
|
* including a distribution deployed on certain nodes of the Amazon
|
||||||
|
* EC2 cluster.
|
||||||
|
* (3) Support for multi-page ring buffers was implemented independently,
|
||||||
|
* in slightly different forms, by both Citrix and RedHat/Amazon.
|
||||||
|
* For full interoperability, block front and backends should publish
|
||||||
|
* identical ring parameters, adjusted for unit differences, to the
|
||||||
|
* XenStore nodes used in both schemes.
|
||||||
|
* (4) Devices that support discard functionality may internally allocate space
|
||||||
|
* (discardable extents) in units that are larger than the exported logical
|
||||||
|
* block size. If the backing device has such discardable extents the
|
||||||
|
* backend should provide both discard-granularity and discard-alignment.
|
||||||
|
* Providing just one of the two may be considered an error by the frontend.
|
||||||
|
* Backends supporting discard should include discard-granularity and
|
||||||
|
* discard-alignment even if it supports discarding individual sectors.
|
||||||
|
* Frontends should assume discard-alignment == 0 and discard-granularity
|
||||||
|
* == sector size if these keys are missing.
|
||||||
|
* (5) The discard-alignment parameter allows a physical device to be
|
||||||
|
* partitioned into virtual devices that do not necessarily begin or
|
||||||
|
* end on a discardable extent boundary.
|
||||||
|
* (6) When there is only a single page allocated to the request ring,
|
||||||
|
* 'ring-ref' is used to communicate the grant reference for this
|
||||||
|
* page to the backend. When using a multi-page ring, the 'ring-ref'
|
||||||
|
* node is not created. Instead 'ring-ref0' - 'ring-refN' are used.
|
||||||
|
* (7) When using persistent grants data has to be copied from/to the page
|
||||||
|
* where the grant is currently mapped. The overhead of doing this copy
|
||||||
|
* however doesn't suppress the speed improvement of not having to unmap
|
||||||
|
* the grants.
|
||||||
|
* (8) The frontend driver has to allow the backend driver to map all grants
|
||||||
|
* with write access, even when they should be mapped read-only, since
|
||||||
|
* further requests may reuse these grants and require write permissions.
|
||||||
|
* (9) Linux implementation doesn't have a limit on the maximum number of
|
||||||
|
* grants that can be persistently mapped in the frontend driver, but
|
||||||
|
* due to the frontent driver implementation it should never be bigger
|
||||||
|
* than RING_SIZE * BLKIF_MAX_SEGMENTS_PER_REQUEST.
|
||||||
|
*(10) The discard-secure property may be present and will be set to 1 if the
|
||||||
|
* backing device supports secure discard.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* STATE DIAGRAMS
|
||||||
|
*
|
||||||
|
*****************************************************************************
|
||||||
|
* Startup *
|
||||||
|
*****************************************************************************
|
||||||
|
*
|
||||||
|
* Tool stack creates front and back nodes with state XenbusStateInitialising.
|
||||||
|
*
|
||||||
|
* Front Back
|
||||||
|
* ================================= =====================================
|
||||||
|
* XenbusStateInitialising XenbusStateInitialising
|
||||||
|
* o Query virtual device o Query backend device identification
|
||||||
|
* properties. data.
|
||||||
|
* o Setup OS device instance. o Open and validate backend device.
|
||||||
|
* o Publish backend features and
|
||||||
|
* transport parameters.
|
||||||
|
* |
|
||||||
|
* |
|
||||||
|
* V
|
||||||
|
* XenbusStateInitWait
|
||||||
|
*
|
||||||
|
* o Query backend features and
|
||||||
|
* transport parameters.
|
||||||
|
* o Allocate and initialize the
|
||||||
|
* request ring.
|
||||||
|
* o Publish transport parameters
|
||||||
|
* that will be in effect during
|
||||||
|
* this connection.
|
||||||
|
* |
|
||||||
|
* |
|
||||||
|
* V
|
||||||
|
* XenbusStateInitialised
|
||||||
|
*
|
||||||
|
* o Query frontend transport parameters.
|
||||||
|
* o Connect to the request ring and
|
||||||
|
* event channel.
|
||||||
|
* o Publish backend device properties.
|
||||||
|
* |
|
||||||
|
* |
|
||||||
|
* V
|
||||||
|
* XenbusStateConnected
|
||||||
|
*
|
||||||
|
* o Query backend device properties.
|
||||||
|
* o Finalize OS virtual device
|
||||||
|
* instance.
|
||||||
|
* |
|
||||||
|
* |
|
||||||
|
* V
|
||||||
|
* XenbusStateConnected
|
||||||
|
*
|
||||||
|
* Note: Drivers that do not support any optional features, or the negotiation
|
||||||
|
* of transport parameters, can skip certain states in the state machine:
|
||||||
|
*
|
||||||
|
* o A frontend may transition to XenbusStateInitialised without
|
||||||
|
* waiting for the backend to enter XenbusStateInitWait. In this
|
||||||
|
* case, default transport parameters are in effect and any
|
||||||
|
* transport parameters published by the frontend must contain
|
||||||
|
* their default values.
|
||||||
|
*
|
||||||
|
* o A backend may transition to XenbusStateInitialised, bypassing
|
||||||
|
* XenbusStateInitWait, without waiting for the frontend to first
|
||||||
|
* enter the XenbusStateInitialised state. In this case, default
|
||||||
|
* transport parameters are in effect and any transport parameters
|
||||||
|
* published by the backend must contain their default values.
|
||||||
|
*
|
||||||
|
* Drivers that support optional features and/or transport parameter
|
||||||
|
* negotiation must tolerate these additional state transition paths.
|
||||||
|
* In general this means performing the work of any skipped state
|
||||||
|
* transition, if it has not already been performed, in addition to the
|
||||||
|
* work associated with entry into the current state.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* REQUEST CODES.
|
||||||
|
*/
|
||||||
|
#define BLKIF_OP_READ 0
|
||||||
|
#define BLKIF_OP_WRITE 1
|
||||||
|
/*
|
||||||
|
* All writes issued prior to a request with the BLKIF_OP_WRITE_BARRIER
|
||||||
|
* operation code ("barrier request") must be completed prior to the
|
||||||
|
* execution of the barrier request. All writes issued after the barrier
|
||||||
|
* request must not execute until after the completion of the barrier request.
|
||||||
|
*
|
||||||
|
* Optional. See "feature-barrier" XenBus node documentation above.
|
||||||
|
*/
|
||||||
|
#define BLKIF_OP_WRITE_BARRIER 2
|
||||||
|
/*
|
||||||
|
* Commit any uncommitted contents of the backing device's volatile cache
|
||||||
|
* to stable storage.
|
||||||
|
*
|
||||||
|
* Optional. See "feature-flush-cache" XenBus node documentation above.
|
||||||
|
*/
|
||||||
|
#define BLKIF_OP_FLUSH_DISKCACHE 3
|
||||||
|
/*
|
||||||
|
* Used in SLES sources for device specific command packet
|
||||||
|
* contained within the request. Reserved for that purpose.
|
||||||
|
*/
|
||||||
|
#define BLKIF_OP_RESERVED_1 4
|
||||||
|
/*
|
||||||
|
* Indicate to the backend device that a region of storage is no longer in
|
||||||
|
* use, and may be discarded at any time without impact to the client. If
|
||||||
|
* the BLKIF_DISCARD_SECURE flag is set on the request, all copies of the
|
||||||
|
* discarded region on the device must be rendered unrecoverable before the
|
||||||
|
* command returns.
|
||||||
|
*
|
||||||
|
* This operation is analogous to performing a trim (ATA) or unamp (SCSI),
|
||||||
|
* command on a native device.
|
||||||
|
*
|
||||||
|
* More information about trim/unmap operations can be found at:
|
||||||
|
* http://t13.org/Documents/UploadedDocuments/docs2008/
|
||||||
|
* e07154r6-Data_Set_Management_Proposal_for_ATA-ACS2.doc
|
||||||
|
* http://www.seagate.com/staticfiles/support/disc/manuals/
|
||||||
|
* Interface%20manuals/100293068c.pdf
|
||||||
|
*
|
||||||
|
* Optional. See "feature-discard", "discard-alignment",
|
||||||
|
* "discard-granularity", and "discard-secure" in the XenBus node
|
||||||
|
* documentation above.
|
||||||
|
*/
|
||||||
|
#define BLKIF_OP_DISCARD 5
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Recognized if "feature-max-indirect-segments" in present in the backend
|
||||||
|
* xenbus info. The "feature-max-indirect-segments" node contains the maximum
|
||||||
|
* number of segments allowed by the backend per request. If the node is
|
||||||
|
* present, the frontend might use blkif_request_indirect structs in order to
|
||||||
|
* issue requests with more than BLKIF_MAX_SEGMENTS_PER_REQUEST (11). The
|
||||||
|
* maximum number of indirect segments is fixed by the backend, but the
|
||||||
|
* frontend can issue requests with any number of indirect segments as long as
|
||||||
|
* it's less than the number provided by the backend. The indirect_grefs field
|
||||||
|
* in blkif_request_indirect should be filled by the frontend with the
|
||||||
|
* grant references of the pages that are holding the indirect segments.
|
||||||
|
* These pages are filled with an array of blkif_request_segment that hold the
|
||||||
|
* information about the segments. The number of indirect pages to use is
|
||||||
|
* determined by the number of segments an indirect request contains. Every
|
||||||
|
* indirect page can contain a maximum of
|
||||||
|
* (PAGE_SIZE / sizeof(struct blkif_request_segment)) segments, so to
|
||||||
|
* calculate the number of indirect pages to use we have to do
|
||||||
|
* ceil(indirect_segments / (PAGE_SIZE / sizeof(struct blkif_request_segment))).
|
||||||
|
*
|
||||||
|
* If a backend does not recognize BLKIF_OP_INDIRECT, it should *not*
|
||||||
|
* create the "feature-max-indirect-segments" node!
|
||||||
|
*/
|
||||||
|
#define BLKIF_OP_INDIRECT 6
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Maximum scatter/gather segments per request.
|
||||||
|
* This is carefully chosen so that sizeof(blkif_ring_t) <= PAGE_SIZE.
|
||||||
|
* NB. This could be 12 if the ring indexes weren't stored in the same page.
|
||||||
|
*/
|
||||||
|
#define BLKIF_MAX_SEGMENTS_PER_REQUEST 11
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Maximum number of indirect pages to use per request.
|
||||||
|
*/
|
||||||
|
#define BLKIF_MAX_INDIRECT_PAGES_PER_REQUEST 8
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NB. first_sect and last_sect in blkif_request_segment, as well as
|
||||||
|
* sector_number in blkif_request, are always expressed in 512-byte units.
|
||||||
|
* However they must be properly aligned to the real sector size of the
|
||||||
|
* physical disk, which is reported in the "physical-sector-size" node in
|
||||||
|
* the backend xenbus info. Also the xenbus "sectors" node is expressed in
|
||||||
|
* 512-byte units.
|
||||||
|
*/
|
||||||
|
struct blkif_request_segment {
|
||||||
|
grant_ref_t gref; /* reference to I/O buffer frame */
|
||||||
|
/* @first_sect: first sector in frame to transfer (inclusive). */
|
||||||
|
/* @last_sect: last sector in frame to transfer (inclusive). */
|
||||||
|
uint8_t first_sect, last_sect;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Starting ring element for any I/O request.
|
||||||
|
*/
|
||||||
|
struct blkif_request {
|
||||||
|
uint8_t operation; /* BLKIF_OP_??? */
|
||||||
|
uint8_t nr_segments; /* number of segments */
|
||||||
|
blkif_vdev_t handle; /* only for read/write requests */
|
||||||
|
uint64_t id; /* private guest value, echoed in resp */
|
||||||
|
blkif_sector_t sector_number;/* start sector idx on disk (r/w only) */
|
||||||
|
struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
|
||||||
|
};
|
||||||
|
typedef struct blkif_request blkif_request_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Cast to this structure when blkif_request.operation == BLKIF_OP_DISCARD
|
||||||
|
* sizeof(struct blkif_request_discard) <= sizeof(struct blkif_request)
|
||||||
|
*/
|
||||||
|
struct blkif_request_discard {
|
||||||
|
uint8_t operation; /* BLKIF_OP_DISCARD */
|
||||||
|
uint8_t flag; /* BLKIF_DISCARD_SECURE or zero */
|
||||||
|
#define BLKIF_DISCARD_SECURE (1<<0) /* ignored if discard-secure=0 */
|
||||||
|
blkif_vdev_t handle; /* same as for read/write requests */
|
||||||
|
uint64_t id; /* private guest value, echoed in resp */
|
||||||
|
blkif_sector_t sector_number;/* start sector idx on disk */
|
||||||
|
uint64_t nr_sectors; /* number of contiguous sectors to discard*/
|
||||||
|
};
|
||||||
|
typedef struct blkif_request_discard blkif_request_discard_t;
|
||||||
|
|
||||||
|
struct blkif_request_indirect {
|
||||||
|
uint8_t operation; /* BLKIF_OP_INDIRECT */
|
||||||
|
uint8_t indirect_op; /* BLKIF_OP_{READ/WRITE} */
|
||||||
|
uint16_t nr_segments; /* number of segments */
|
||||||
|
uint64_t id; /* private guest value, echoed in resp */
|
||||||
|
blkif_sector_t sector_number;/* start sector idx on disk (r/w only) */
|
||||||
|
blkif_vdev_t handle; /* same as for read/write requests */
|
||||||
|
grant_ref_t indirect_grefs[BLKIF_MAX_INDIRECT_PAGES_PER_REQUEST];
|
||||||
|
#ifdef __i386__
|
||||||
|
uint64_t pad; /* Make it 64 byte aligned on i386 */
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
typedef struct blkif_request_indirect blkif_request_indirect_t;
|
||||||
|
|
||||||
|
struct blkif_response {
|
||||||
|
uint64_t id; /* copied from request */
|
||||||
|
uint8_t operation; /* copied from request */
|
||||||
|
int16_t status; /* BLKIF_RSP_??? */
|
||||||
|
};
|
||||||
|
typedef struct blkif_response blkif_response_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* STATUS RETURN CODES.
|
||||||
|
*/
|
||||||
|
/* Operation not supported (only happens on barrier writes). */
|
||||||
|
#define BLKIF_RSP_EOPNOTSUPP -2
|
||||||
|
/* Operation failed for some unspecified reason (-EIO). */
|
||||||
|
#define BLKIF_RSP_ERROR -1
|
||||||
|
/* Operation completed successfully. */
|
||||||
|
#define BLKIF_RSP_OKAY 0
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generate blkif ring structures and types.
|
||||||
|
*/
|
||||||
|
DEFINE_RING_TYPES(blkif, struct blkif_request, struct blkif_response);
|
||||||
|
|
||||||
|
#define VDISK_CDROM 0x1
|
||||||
|
#define VDISK_REMOVABLE 0x2
|
||||||
|
#define VDISK_READONLY 0x4
|
||||||
|
|
||||||
|
#endif /* __XEN_PUBLIC_IO_BLKIF_H__ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local variables:
|
||||||
|
* mode: C
|
||||||
|
* c-file-style: "BSD"
|
||||||
|
* c-basic-offset: 4
|
||||||
|
* tab-width: 4
|
||||||
|
* indent-tabs-mode: nil
|
||||||
|
* End:
|
||||||
|
*/
|
51
include/xen/io/console.h
Normal file
51
include/xen/io/console.h
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* console.h
|
||||||
|
*
|
||||||
|
* Console I/O interface for Xen guest OSes.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to
|
||||||
|
* deal in the Software without restriction, including without limitation the
|
||||||
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
* sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2005, Keir Fraser
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __XEN_PUBLIC_IO_CONSOLE_H__
|
||||||
|
#define __XEN_PUBLIC_IO_CONSOLE_H__
|
||||||
|
|
||||||
|
typedef uint32_t XENCONS_RING_IDX;
|
||||||
|
|
||||||
|
#define MASK_XENCONS_IDX(idx, ring) ((idx) & (sizeof(ring)-1))
|
||||||
|
|
||||||
|
struct xencons_interface {
|
||||||
|
char in[1024];
|
||||||
|
char out[2048];
|
||||||
|
XENCONS_RING_IDX in_cons, in_prod;
|
||||||
|
XENCONS_RING_IDX out_cons, out_prod;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* __XEN_PUBLIC_IO_CONSOLE_H__ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local variables:
|
||||||
|
* mode: C
|
||||||
|
* c-file-style: "BSD"
|
||||||
|
* c-basic-offset: 4
|
||||||
|
* tab-width: 4
|
||||||
|
* indent-tabs-mode: nil
|
||||||
|
* End:
|
||||||
|
*/
|
40
include/xen/io/protocols.h
Normal file
40
include/xen/io/protocols.h
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* protocols.h
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to
|
||||||
|
* deal in the Software without restriction, including without limitation the
|
||||||
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
* sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __XEN_PROTOCOLS_H__
|
||||||
|
#define __XEN_PROTOCOLS_H__
|
||||||
|
|
||||||
|
#define XEN_IO_PROTO_ABI_X86_32 "x86_32-abi"
|
||||||
|
#define XEN_IO_PROTO_ABI_X86_64 "x86_64-abi"
|
||||||
|
#define XEN_IO_PROTO_ABI_ARM "arm-abi"
|
||||||
|
|
||||||
|
#if defined(__i386__)
|
||||||
|
# define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_X86_32
|
||||||
|
#elif defined(__x86_64__)
|
||||||
|
# define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_X86_64
|
||||||
|
#elif defined(__arm__) || defined(__aarch64__)
|
||||||
|
# define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_ARM
|
||||||
|
#else
|
||||||
|
# error arch fixup needed here
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
312
include/xen/io/ring.h
Normal file
312
include/xen/io/ring.h
Normal file
|
@ -0,0 +1,312 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* ring.h
|
||||||
|
*
|
||||||
|
* Shared producer-consumer ring macros.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to
|
||||||
|
* deal in the Software without restriction, including without limitation the
|
||||||
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
* sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* Tim Deegan and Andrew Warfield November 2004.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __XEN_PUBLIC_IO_RING_H__
|
||||||
|
#define __XEN_PUBLIC_IO_RING_H__
|
||||||
|
|
||||||
|
#include "../xen-compat.h"
|
||||||
|
|
||||||
|
#if __XEN_INTERFACE_VERSION__ < 0x00030208
|
||||||
|
#define xen_mb() mb()
|
||||||
|
#define xen_rmb() rmb()
|
||||||
|
#define xen_wmb() wmb()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef unsigned int RING_IDX;
|
||||||
|
|
||||||
|
/* Round a 32-bit unsigned constant down to the nearest power of two. */
|
||||||
|
#define __RD2(_x) (((_x) & 0x00000002) ? 0x2 : ((_x) & 0x1))
|
||||||
|
#define __RD4(_x) (((_x) & 0x0000000c) ? __RD2((_x)>>2)<<2 : __RD2(_x))
|
||||||
|
#define __RD8(_x) (((_x) & 0x000000f0) ? __RD4((_x)>>4)<<4 : __RD4(_x))
|
||||||
|
#define __RD16(_x) (((_x) & 0x0000ff00) ? __RD8((_x)>>8)<<8 : __RD8(_x))
|
||||||
|
#define __RD32(_x) (((_x) & 0xffff0000) ? __RD16((_x)>>16)<<16 : __RD16(_x))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Calculate size of a shared ring, given the total available space for the
|
||||||
|
* ring and indexes (_sz), and the name tag of the request/response structure.
|
||||||
|
* A ring contains as many entries as will fit, rounded down to the nearest
|
||||||
|
* power of two (so we can mask with (size-1) to loop around).
|
||||||
|
*/
|
||||||
|
#define __CONST_RING_SIZE(_s, _sz) \
|
||||||
|
(__RD32(((_sz) - offsetof(struct _s##_sring, ring)) / \
|
||||||
|
sizeof(((struct _s##_sring *)0)->ring[0])))
|
||||||
|
/*
|
||||||
|
* The same for passing in an actual pointer instead of a name tag.
|
||||||
|
*/
|
||||||
|
#define __RING_SIZE(_s, _sz) \
|
||||||
|
(__RD32(((_sz) - (long)(_s)->ring + (long)(_s)) / sizeof((_s)->ring[0])))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Macros to make the correct C datatypes for a new kind of ring.
|
||||||
|
*
|
||||||
|
* To make a new ring datatype, you need to have two message structures,
|
||||||
|
* let's say request_t, and response_t already defined.
|
||||||
|
*
|
||||||
|
* In a header where you want the ring datatype declared, you then do:
|
||||||
|
*
|
||||||
|
* DEFINE_RING_TYPES(mytag, request_t, response_t);
|
||||||
|
*
|
||||||
|
* These expand out to give you a set of types, as you can see below.
|
||||||
|
* The most important of these are:
|
||||||
|
*
|
||||||
|
* mytag_sring_t - The shared ring.
|
||||||
|
* mytag_front_ring_t - The 'front' half of the ring.
|
||||||
|
* mytag_back_ring_t - The 'back' half of the ring.
|
||||||
|
*
|
||||||
|
* To initialize a ring in your code you need to know the location and size
|
||||||
|
* of the shared memory area (PAGE_SIZE, for instance). To initialise
|
||||||
|
* the front half:
|
||||||
|
*
|
||||||
|
* mytag_front_ring_t front_ring;
|
||||||
|
* SHARED_RING_INIT((mytag_sring_t *)shared_page);
|
||||||
|
* FRONT_RING_INIT(&front_ring, (mytag_sring_t *)shared_page, PAGE_SIZE);
|
||||||
|
*
|
||||||
|
* Initializing the back follows similarly (note that only the front
|
||||||
|
* initializes the shared ring):
|
||||||
|
*
|
||||||
|
* mytag_back_ring_t back_ring;
|
||||||
|
* BACK_RING_INIT(&back_ring, (mytag_sring_t *)shared_page, PAGE_SIZE);
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DEFINE_RING_TYPES(__name, __req_t, __rsp_t) \
|
||||||
|
\
|
||||||
|
/* Shared ring entry */ \
|
||||||
|
union __name##_sring_entry { \
|
||||||
|
__req_t req; \
|
||||||
|
__rsp_t rsp; \
|
||||||
|
}; \
|
||||||
|
\
|
||||||
|
/* Shared ring page */ \
|
||||||
|
struct __name##_sring { \
|
||||||
|
RING_IDX req_prod, req_event; \
|
||||||
|
RING_IDX rsp_prod, rsp_event; \
|
||||||
|
union { \
|
||||||
|
struct { \
|
||||||
|
uint8_t smartpoll_active; \
|
||||||
|
} netif; \
|
||||||
|
struct { \
|
||||||
|
uint8_t msg; \
|
||||||
|
} tapif_user; \
|
||||||
|
uint8_t pvt_pad[4]; \
|
||||||
|
} private; \
|
||||||
|
uint8_t __pad[44]; \
|
||||||
|
union __name##_sring_entry ring[1]; /* variable-length */ \
|
||||||
|
}; \
|
||||||
|
\
|
||||||
|
/* "Front" end's private variables */ \
|
||||||
|
struct __name##_front_ring { \
|
||||||
|
RING_IDX req_prod_pvt; \
|
||||||
|
RING_IDX rsp_cons; \
|
||||||
|
unsigned int nr_ents; \
|
||||||
|
struct __name##_sring *sring; \
|
||||||
|
}; \
|
||||||
|
\
|
||||||
|
/* "Back" end's private variables */ \
|
||||||
|
struct __name##_back_ring { \
|
||||||
|
RING_IDX rsp_prod_pvt; \
|
||||||
|
RING_IDX req_cons; \
|
||||||
|
unsigned int nr_ents; \
|
||||||
|
struct __name##_sring *sring; \
|
||||||
|
}; \
|
||||||
|
\
|
||||||
|
/* Syntactic sugar */ \
|
||||||
|
typedef struct __name##_sring __name##_sring_t; \
|
||||||
|
typedef struct __name##_front_ring __name##_front_ring_t; \
|
||||||
|
typedef struct __name##_back_ring __name##_back_ring_t
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Macros for manipulating rings.
|
||||||
|
*
|
||||||
|
* FRONT_RING_whatever works on the "front end" of a ring: here
|
||||||
|
* requests are pushed on to the ring and responses taken off it.
|
||||||
|
*
|
||||||
|
* BACK_RING_whatever works on the "back end" of a ring: here
|
||||||
|
* requests are taken off the ring and responses put on.
|
||||||
|
*
|
||||||
|
* N.B. these macros do NO INTERLOCKS OR FLOW CONTROL.
|
||||||
|
* This is OK in 1-for-1 request-response situations where the
|
||||||
|
* requestor (front end) never has more than RING_SIZE()-1
|
||||||
|
* outstanding requests.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Initialising empty rings */
|
||||||
|
#define SHARED_RING_INIT(_s) do { \
|
||||||
|
(_s)->req_prod = (_s)->rsp_prod = 0; \
|
||||||
|
(_s)->req_event = (_s)->rsp_event = 1; \
|
||||||
|
(void)memset((_s)->private.pvt_pad, 0, sizeof((_s)->private.pvt_pad)); \
|
||||||
|
(void)memset((_s)->__pad, 0, sizeof((_s)->__pad)); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define FRONT_RING_INIT(_r, _s, __size) do { \
|
||||||
|
(_r)->req_prod_pvt = 0; \
|
||||||
|
(_r)->rsp_cons = 0; \
|
||||||
|
(_r)->nr_ents = __RING_SIZE(_s, __size); \
|
||||||
|
(_r)->sring = (_s); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define BACK_RING_INIT(_r, _s, __size) do { \
|
||||||
|
(_r)->rsp_prod_pvt = 0; \
|
||||||
|
(_r)->req_cons = 0; \
|
||||||
|
(_r)->nr_ents = __RING_SIZE(_s, __size); \
|
||||||
|
(_r)->sring = (_s); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/* How big is this ring? */
|
||||||
|
#define RING_SIZE(_r) \
|
||||||
|
((_r)->nr_ents)
|
||||||
|
|
||||||
|
/* Number of free requests (for use on front side only). */
|
||||||
|
#define RING_FREE_REQUESTS(_r) \
|
||||||
|
(RING_SIZE(_r) - ((_r)->req_prod_pvt - (_r)->rsp_cons))
|
||||||
|
|
||||||
|
/* Test if there is an empty slot available on the front ring.
|
||||||
|
* (This is only meaningful from the front. )
|
||||||
|
*/
|
||||||
|
#define RING_FULL(_r) \
|
||||||
|
(RING_FREE_REQUESTS(_r) == 0)
|
||||||
|
|
||||||
|
/* Test if there are outstanding messages to be processed on a ring. */
|
||||||
|
#define RING_HAS_UNCONSUMED_RESPONSES(_r) \
|
||||||
|
((_r)->sring->rsp_prod - (_r)->rsp_cons)
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#define RING_HAS_UNCONSUMED_REQUESTS(_r) ({ \
|
||||||
|
unsigned int req = (_r)->sring->req_prod - (_r)->req_cons; \
|
||||||
|
unsigned int rsp = RING_SIZE(_r) - \
|
||||||
|
((_r)->req_cons - (_r)->rsp_prod_pvt); \
|
||||||
|
req < rsp ? req : rsp; \
|
||||||
|
})
|
||||||
|
#else
|
||||||
|
/* Same as above, but without the nice GCC ({ ... }) syntax. */
|
||||||
|
#define RING_HAS_UNCONSUMED_REQUESTS(_r) \
|
||||||
|
((((_r)->sring->req_prod - (_r)->req_cons) < \
|
||||||
|
(RING_SIZE(_r) - ((_r)->req_cons - (_r)->rsp_prod_pvt))) ? \
|
||||||
|
((_r)->sring->req_prod - (_r)->req_cons) : \
|
||||||
|
(RING_SIZE(_r) - ((_r)->req_cons - (_r)->rsp_prod_pvt)))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Direct access to individual ring elements, by index. */
|
||||||
|
#define RING_GET_REQUEST(_r, _idx) \
|
||||||
|
(&((_r)->sring->ring[((_idx) & (RING_SIZE(_r) - 1))].req))
|
||||||
|
|
||||||
|
#define RING_GET_RESPONSE(_r, _idx) \
|
||||||
|
(&((_r)->sring->ring[((_idx) & (RING_SIZE(_r) - 1))].rsp))
|
||||||
|
|
||||||
|
/* Loop termination condition: Would the specified index overflow the ring? */
|
||||||
|
#define RING_REQUEST_CONS_OVERFLOW(_r, _cons) \
|
||||||
|
(((_cons) - (_r)->rsp_prod_pvt) >= RING_SIZE(_r))
|
||||||
|
|
||||||
|
/* Ill-behaved frontend determination: Can there be this many requests? */
|
||||||
|
#define RING_REQUEST_PROD_OVERFLOW(_r, _prod) \
|
||||||
|
(((_prod) - (_r)->rsp_prod_pvt) > RING_SIZE(_r))
|
||||||
|
|
||||||
|
#define RING_PUSH_REQUESTS(_r) do { \
|
||||||
|
xen_wmb(); /* back sees requests /before/ updated producer index */ \
|
||||||
|
(_r)->sring->req_prod = (_r)->req_prod_pvt; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define RING_PUSH_RESPONSES(_r) do { \
|
||||||
|
xen_wmb(); /* front sees resps /before/ updated producer index */ \
|
||||||
|
(_r)->sring->rsp_prod = (_r)->rsp_prod_pvt; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Notification hold-off (req_event and rsp_event):
|
||||||
|
*
|
||||||
|
* When queueing requests or responses on a shared ring, it may not always be
|
||||||
|
* necessary to notify the remote end. For example, if requests are in flight
|
||||||
|
* in a backend, the front may be able to queue further requests without
|
||||||
|
* notifying the back (if the back checks for new requests when it queues
|
||||||
|
* responses).
|
||||||
|
*
|
||||||
|
* When enqueuing requests or responses:
|
||||||
|
*
|
||||||
|
* Use RING_PUSH_{REQUESTS,RESPONSES}_AND_CHECK_NOTIFY(). The second argument
|
||||||
|
* is a boolean return value. True indicates that the receiver requires an
|
||||||
|
* asynchronous notification.
|
||||||
|
*
|
||||||
|
* After dequeuing requests or responses (before sleeping the connection):
|
||||||
|
*
|
||||||
|
* Use RING_FINAL_CHECK_FOR_REQUESTS() or RING_FINAL_CHECK_FOR_RESPONSES().
|
||||||
|
* The second argument is a boolean return value. True indicates that there
|
||||||
|
* are pending messages on the ring (i.e., the connection should not be put
|
||||||
|
* to sleep).
|
||||||
|
*
|
||||||
|
* These macros will set the req_event/rsp_event field to trigger a
|
||||||
|
* notification on the very next message that is enqueued. If you want to
|
||||||
|
* create batches of work (i.e., only receive a notification after several
|
||||||
|
* messages have been enqueued) then you will need to create a customised
|
||||||
|
* version of the FINAL_CHECK macro in your own code, which sets the event
|
||||||
|
* field appropriately.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(_r, _notify) do { \
|
||||||
|
RING_IDX __old = (_r)->sring->req_prod; \
|
||||||
|
RING_IDX __new = (_r)->req_prod_pvt; \
|
||||||
|
xen_wmb(); /* back sees requests /before/ updated producer index */ \
|
||||||
|
(_r)->sring->req_prod = __new; \
|
||||||
|
xen_mb(); /* back sees new requests /before/ we check req_event */ \
|
||||||
|
(_notify) = ((RING_IDX)(__new - (_r)->sring->req_event) < \
|
||||||
|
(RING_IDX)(__new - __old)); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(_r, _notify) do { \
|
||||||
|
RING_IDX __old = (_r)->sring->rsp_prod; \
|
||||||
|
RING_IDX __new = (_r)->rsp_prod_pvt; \
|
||||||
|
xen_wmb(); /* front sees resps /before/ updated producer index */ \
|
||||||
|
(_r)->sring->rsp_prod = __new; \
|
||||||
|
xen_mb(); /* front sees new resps /before/ we check rsp_event */ \
|
||||||
|
(_notify) = ((RING_IDX)(__new - (_r)->sring->rsp_event) < \
|
||||||
|
(RING_IDX)(__new - __old)); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define RING_FINAL_CHECK_FOR_REQUESTS(_r, _work_to_do) do { \
|
||||||
|
(_work_to_do) = RING_HAS_UNCONSUMED_REQUESTS(_r); \
|
||||||
|
if (_work_to_do) break; \
|
||||||
|
(_r)->sring->req_event = (_r)->req_cons + 1; \
|
||||||
|
xen_mb(); \
|
||||||
|
(_work_to_do) = RING_HAS_UNCONSUMED_REQUESTS(_r); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define RING_FINAL_CHECK_FOR_RESPONSES(_r, _work_to_do) do { \
|
||||||
|
(_work_to_do) = RING_HAS_UNCONSUMED_RESPONSES(_r); \
|
||||||
|
if (_work_to_do) break; \
|
||||||
|
(_r)->sring->rsp_event = (_r)->rsp_cons + 1; \
|
||||||
|
xen_mb(); \
|
||||||
|
(_work_to_do) = RING_HAS_UNCONSUMED_RESPONSES(_r); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#endif /* __XEN_PUBLIC_IO_RING_H__ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local variables:
|
||||||
|
* mode: C
|
||||||
|
* c-file-style: "BSD"
|
||||||
|
* c-basic-offset: 4
|
||||||
|
* tab-width: 4
|
||||||
|
* indent-tabs-mode: nil
|
||||||
|
* End:
|
||||||
|
*/
|
80
include/xen/io/xenbus.h
Normal file
80
include/xen/io/xenbus.h
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
/*****************************************************************************
|
||||||
|
* xenbus.h
|
||||||
|
*
|
||||||
|
* Xenbus protocol details.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to
|
||||||
|
* deal in the Software without restriction, including without limitation the
|
||||||
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
* sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2005 XenSource Ltd.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _XEN_PUBLIC_IO_XENBUS_H
|
||||||
|
#define _XEN_PUBLIC_IO_XENBUS_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The state of either end of the Xenbus, i.e. the current communication
|
||||||
|
* status of initialisation across the bus. States here imply nothing about
|
||||||
|
* the state of the connection between the driver and the kernel's device
|
||||||
|
* layers.
|
||||||
|
*/
|
||||||
|
enum xenbus_state {
|
||||||
|
XenbusStateUnknown = 0,
|
||||||
|
|
||||||
|
XenbusStateInitialising = 1,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* InitWait: Finished early initialisation but waiting for information
|
||||||
|
* from the peer or hotplug scripts.
|
||||||
|
*/
|
||||||
|
XenbusStateInitWait = 2,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialised: Waiting for a connection from the peer.
|
||||||
|
*/
|
||||||
|
XenbusStateInitialised = 3,
|
||||||
|
|
||||||
|
XenbusStateConnected = 4,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Closing: The device is being closed due to an error or an unplug event.
|
||||||
|
*/
|
||||||
|
XenbusStateClosing = 5,
|
||||||
|
|
||||||
|
XenbusStateClosed = 6,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reconfiguring: The device is being reconfigured.
|
||||||
|
*/
|
||||||
|
XenbusStateReconfiguring = 7,
|
||||||
|
|
||||||
|
XenbusStateReconfigured = 8
|
||||||
|
};
|
||||||
|
typedef enum xenbus_state XenbusState;
|
||||||
|
|
||||||
|
#endif /* _XEN_PUBLIC_IO_XENBUS_H */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local variables:
|
||||||
|
* mode: C
|
||||||
|
* c-file-style: "BSD"
|
||||||
|
* c-basic-offset: 4
|
||||||
|
* tab-width: 4
|
||||||
|
* indent-tabs-mode: nil
|
||||||
|
* End:
|
||||||
|
*/
|
138
include/xen/io/xs_wire.h
Normal file
138
include/xen/io/xs_wire.h
Normal file
|
@ -0,0 +1,138 @@
|
||||||
|
/*
|
||||||
|
* Details of the "wire" protocol between Xen Store Daemon and client
|
||||||
|
* library or guest kernel.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to
|
||||||
|
* deal in the Software without restriction, including without limitation the
|
||||||
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
* sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2005 Rusty Russell IBM Corporation
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _XS_WIRE_H
|
||||||
|
#define _XS_WIRE_H
|
||||||
|
|
||||||
|
enum xsd_sockmsg_type
|
||||||
|
{
|
||||||
|
XS_DEBUG,
|
||||||
|
XS_DIRECTORY,
|
||||||
|
XS_READ,
|
||||||
|
XS_GET_PERMS,
|
||||||
|
XS_WATCH,
|
||||||
|
XS_UNWATCH,
|
||||||
|
XS_TRANSACTION_START,
|
||||||
|
XS_TRANSACTION_END,
|
||||||
|
XS_INTRODUCE,
|
||||||
|
XS_RELEASE,
|
||||||
|
XS_GET_DOMAIN_PATH,
|
||||||
|
XS_WRITE,
|
||||||
|
XS_MKDIR,
|
||||||
|
XS_RM,
|
||||||
|
XS_SET_PERMS,
|
||||||
|
XS_WATCH_EVENT,
|
||||||
|
XS_ERROR,
|
||||||
|
XS_IS_DOMAIN_INTRODUCED,
|
||||||
|
XS_RESUME,
|
||||||
|
XS_SET_TARGET,
|
||||||
|
XS_RESTRICT,
|
||||||
|
XS_RESET_WATCHES
|
||||||
|
};
|
||||||
|
|
||||||
|
#define XS_WRITE_NONE "NONE"
|
||||||
|
#define XS_WRITE_CREATE "CREATE"
|
||||||
|
#define XS_WRITE_CREATE_EXCL "CREATE|EXCL"
|
||||||
|
|
||||||
|
/* We hand errors as strings, for portability. */
|
||||||
|
struct xsd_errors
|
||||||
|
{
|
||||||
|
int errnum;
|
||||||
|
const char *errstring;
|
||||||
|
};
|
||||||
|
#ifdef EINVAL
|
||||||
|
#define XSD_ERROR(x) { x, #x }
|
||||||
|
/* LINTED: static unused */
|
||||||
|
static struct xsd_errors xsd_errors[]
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
__attribute__((unused))
|
||||||
|
#endif
|
||||||
|
= {
|
||||||
|
XSD_ERROR(EINVAL),
|
||||||
|
XSD_ERROR(EACCES),
|
||||||
|
XSD_ERROR(EEXIST),
|
||||||
|
XSD_ERROR(EISDIR),
|
||||||
|
XSD_ERROR(ENOENT),
|
||||||
|
XSD_ERROR(ENOMEM),
|
||||||
|
XSD_ERROR(ENOSPC),
|
||||||
|
XSD_ERROR(EIO),
|
||||||
|
XSD_ERROR(ENOTEMPTY),
|
||||||
|
XSD_ERROR(ENOSYS),
|
||||||
|
XSD_ERROR(EROFS),
|
||||||
|
XSD_ERROR(EBUSY),
|
||||||
|
XSD_ERROR(EAGAIN),
|
||||||
|
XSD_ERROR(EISCONN),
|
||||||
|
XSD_ERROR(E2BIG)
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct xsd_sockmsg
|
||||||
|
{
|
||||||
|
uint32_t type; /* XS_??? */
|
||||||
|
uint32_t req_id;/* Request identifier, echoed in daemon's response. */
|
||||||
|
uint32_t tx_id; /* Transaction id (0 if not related to a transaction). */
|
||||||
|
uint32_t len; /* Length of data following this. */
|
||||||
|
|
||||||
|
/* Generally followed by nul-terminated string(s). */
|
||||||
|
};
|
||||||
|
|
||||||
|
enum xs_watch_type
|
||||||
|
{
|
||||||
|
XS_WATCH_PATH = 0,
|
||||||
|
XS_WATCH_TOKEN
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* `incontents 150 xenstore_struct XenStore wire protocol.
|
||||||
|
*
|
||||||
|
* Inter-domain shared memory communications. */
|
||||||
|
#define XENSTORE_RING_SIZE 1024
|
||||||
|
typedef uint32_t XENSTORE_RING_IDX;
|
||||||
|
#define MASK_XENSTORE_IDX(idx) ((idx) & (XENSTORE_RING_SIZE-1))
|
||||||
|
struct xenstore_domain_interface {
|
||||||
|
char req[XENSTORE_RING_SIZE]; /* Requests to xenstore daemon. */
|
||||||
|
char rsp[XENSTORE_RING_SIZE]; /* Replies and async watch events. */
|
||||||
|
XENSTORE_RING_IDX req_cons, req_prod;
|
||||||
|
XENSTORE_RING_IDX rsp_cons, rsp_prod;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Violating this is very bad. See docs/misc/xenstore.txt. */
|
||||||
|
#define XENSTORE_PAYLOAD_MAX 4096
|
||||||
|
|
||||||
|
/* Violating these just gets you an error back */
|
||||||
|
#define XENSTORE_ABS_PATH_MAX 3072
|
||||||
|
#define XENSTORE_REL_PATH_MAX 2048
|
||||||
|
|
||||||
|
#endif /* _XS_WIRE_H */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local variables:
|
||||||
|
* mode: C
|
||||||
|
* c-file-style: "BSD"
|
||||||
|
* c-basic-offset: 4
|
||||||
|
* tab-width: 4
|
||||||
|
* indent-tabs-mode: nil
|
||||||
|
* End:
|
||||||
|
*/
|
174
include/xen/sched.h
Normal file
174
include/xen/sched.h
Normal file
|
@ -0,0 +1,174 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* sched.h
|
||||||
|
*
|
||||||
|
* Scheduler state interactions
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to
|
||||||
|
* deal in the Software without restriction, including without limitation the
|
||||||
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
* sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2005, Keir Fraser <keir@xensource.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __XEN_PUBLIC_SCHED_H__
|
||||||
|
#define __XEN_PUBLIC_SCHED_H__
|
||||||
|
|
||||||
|
#include "event_channel.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* `incontents 150 sched Guest Scheduler Operations
|
||||||
|
*
|
||||||
|
* The SCHEDOP interface provides mechanisms for a guest to interact
|
||||||
|
* with the scheduler, including yield, blocking and shutting itself
|
||||||
|
* down.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The prototype for this hypercall is:
|
||||||
|
* ` long HYPERVISOR_sched_op(enum sched_op cmd, void *arg, ...)
|
||||||
|
*
|
||||||
|
* @cmd == SCHEDOP_??? (scheduler operation).
|
||||||
|
* @arg == Operation-specific extra argument(s), as described below.
|
||||||
|
* ... == Additional Operation-specific extra arguments, described below.
|
||||||
|
*
|
||||||
|
* Versions of Xen prior to 3.0.2 provided only the following legacy version
|
||||||
|
* of this hypercall, supporting only the commands yield, block and shutdown:
|
||||||
|
* long sched_op(int cmd, unsigned long arg)
|
||||||
|
* @cmd == SCHEDOP_??? (scheduler operation).
|
||||||
|
* @arg == 0 (SCHEDOP_yield and SCHEDOP_block)
|
||||||
|
* == SHUTDOWN_* code (SCHEDOP_shutdown)
|
||||||
|
*
|
||||||
|
* This legacy version is available to new guests as:
|
||||||
|
* ` long HYPERVISOR_sched_op_compat(enum sched_op cmd, unsigned long arg)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ` enum sched_op { // SCHEDOP_* => struct sched_* */
|
||||||
|
/*
|
||||||
|
* Voluntarily yield the CPU.
|
||||||
|
* @arg == NULL.
|
||||||
|
*/
|
||||||
|
#define SCHEDOP_yield 0
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Block execution of this VCPU until an event is received for processing.
|
||||||
|
* If called with event upcalls masked, this operation will atomically
|
||||||
|
* reenable event delivery and check for pending events before blocking the
|
||||||
|
* VCPU. This avoids a "wakeup waiting" race.
|
||||||
|
* @arg == NULL.
|
||||||
|
*/
|
||||||
|
#define SCHEDOP_block 1
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Halt execution of this domain (all VCPUs) and notify the system controller.
|
||||||
|
* @arg == pointer to sched_shutdown_t structure.
|
||||||
|
*
|
||||||
|
* If the sched_shutdown_t reason is SHUTDOWN_suspend then this
|
||||||
|
* hypercall takes an additional extra argument which should be the
|
||||||
|
* MFN of the guest's start_info_t.
|
||||||
|
*
|
||||||
|
* In addition, which reason is SHUTDOWN_suspend this hypercall
|
||||||
|
* returns 1 if suspend was cancelled or the domain was merely
|
||||||
|
* checkpointed, and 0 if it is resuming in a new domain.
|
||||||
|
*/
|
||||||
|
#define SCHEDOP_shutdown 2
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Poll a set of event-channel ports. Return when one or more are pending. An
|
||||||
|
* optional timeout may be specified.
|
||||||
|
* @arg == pointer to sched_poll_t structure.
|
||||||
|
*/
|
||||||
|
#define SCHEDOP_poll 3
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Declare a shutdown for another domain. The main use of this function is
|
||||||
|
* in interpreting shutdown requests and reasons for fully-virtualized
|
||||||
|
* domains. A para-virtualized domain may use SCHEDOP_shutdown directly.
|
||||||
|
* @arg == pointer to sched_remote_shutdown_t structure.
|
||||||
|
*/
|
||||||
|
#define SCHEDOP_remote_shutdown 4
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Latch a shutdown code, so that when the domain later shuts down it
|
||||||
|
* reports this code to the control tools.
|
||||||
|
* @arg == sched_shutdown_t, as for SCHEDOP_shutdown.
|
||||||
|
*/
|
||||||
|
#define SCHEDOP_shutdown_code 5
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Setup, poke and destroy a domain watchdog timer.
|
||||||
|
* @arg == pointer to sched_watchdog_t structure.
|
||||||
|
* With id == 0, setup a domain watchdog timer to cause domain shutdown
|
||||||
|
* after timeout, returns watchdog id.
|
||||||
|
* With id != 0 and timeout == 0, destroy domain watchdog timer.
|
||||||
|
* With id != 0 and timeout != 0, poke watchdog timer and set new timeout.
|
||||||
|
*/
|
||||||
|
#define SCHEDOP_watchdog 6
|
||||||
|
/* ` } */
|
||||||
|
|
||||||
|
struct sched_shutdown {
|
||||||
|
unsigned int reason; /* SHUTDOWN_* => enum sched_shutdown_reason */
|
||||||
|
};
|
||||||
|
typedef struct sched_shutdown sched_shutdown_t;
|
||||||
|
DEFINE_XEN_GUEST_HANDLE(sched_shutdown_t);
|
||||||
|
|
||||||
|
struct sched_poll {
|
||||||
|
XEN_GUEST_HANDLE(evtchn_port_t) ports;
|
||||||
|
unsigned int nr_ports;
|
||||||
|
uint64_t timeout;
|
||||||
|
};
|
||||||
|
typedef struct sched_poll sched_poll_t;
|
||||||
|
DEFINE_XEN_GUEST_HANDLE(sched_poll_t);
|
||||||
|
|
||||||
|
struct sched_remote_shutdown {
|
||||||
|
domid_t domain_id; /* Remote domain ID */
|
||||||
|
unsigned int reason; /* SHUTDOWN_* => enum sched_shutdown_reason */
|
||||||
|
};
|
||||||
|
typedef struct sched_remote_shutdown sched_remote_shutdown_t;
|
||||||
|
DEFINE_XEN_GUEST_HANDLE(sched_remote_shutdown_t);
|
||||||
|
|
||||||
|
struct sched_watchdog {
|
||||||
|
uint32_t id; /* watchdog ID */
|
||||||
|
uint32_t timeout; /* timeout */
|
||||||
|
};
|
||||||
|
typedef struct sched_watchdog sched_watchdog_t;
|
||||||
|
DEFINE_XEN_GUEST_HANDLE(sched_watchdog_t);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reason codes for SCHEDOP_shutdown. These may be interpreted by control
|
||||||
|
* software to determine the appropriate action. For the most part, Xen does
|
||||||
|
* not care about the shutdown code.
|
||||||
|
*/
|
||||||
|
/* ` enum sched_shutdown_reason { */
|
||||||
|
#define SHUTDOWN_poweroff 0 /* Domain exited normally. Clean up and kill. */
|
||||||
|
#define SHUTDOWN_reboot 1 /* Clean up, kill, and then restart. */
|
||||||
|
#define SHUTDOWN_suspend 2 /* Clean up, save suspend info, kill. */
|
||||||
|
#define SHUTDOWN_crash 3 /* Tell controller we've crashed. */
|
||||||
|
#define SHUTDOWN_watchdog 4 /* Restart because watchdog time expired. */
|
||||||
|
#define SHUTDOWN_MAX 4 /* Maximum valid shutdown reason. */
|
||||||
|
/* ` } */
|
||||||
|
|
||||||
|
#endif /* __XEN_PUBLIC_SCHED_H__ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local variables:
|
||||||
|
* mode: C
|
||||||
|
* c-file-style: "BSD"
|
||||||
|
* c-basic-offset: 4
|
||||||
|
* tab-width: 4
|
||||||
|
* indent-tabs-mode: nil
|
||||||
|
* End:
|
||||||
|
*/
|
44
include/xen/xen-compat.h
Normal file
44
include/xen/xen-compat.h
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* xen-compat.h
|
||||||
|
*
|
||||||
|
* Guest OS interface to Xen. Compatibility layer.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to
|
||||||
|
* deal in the Software without restriction, including without limitation the
|
||||||
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
* sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006, Christian Limpach
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __XEN_PUBLIC_XEN_COMPAT_H__
|
||||||
|
#define __XEN_PUBLIC_XEN_COMPAT_H__
|
||||||
|
|
||||||
|
#define __XEN_LATEST_INTERFACE_VERSION__ 0x00040400
|
||||||
|
|
||||||
|
#if defined(__XEN__) || defined(__XEN_TOOLS__)
|
||||||
|
/* Xen is built with matching headers and implements the latest interface. */
|
||||||
|
#define __XEN_INTERFACE_VERSION__ __XEN_LATEST_INTERFACE_VERSION__
|
||||||
|
#elif !defined(__XEN_INTERFACE_VERSION__)
|
||||||
|
/* Guests which do not specify a version get the legacy interface. */
|
||||||
|
#define __XEN_INTERFACE_VERSION__ 0x00000000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if __XEN_INTERFACE_VERSION__ > __XEN_LATEST_INTERFACE_VERSION__
|
||||||
|
#error "These header files do not support the requested interface version."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __XEN_PUBLIC_XEN_COMPAT_H__ */
|
899
include/xen/xen.h
Normal file
899
include/xen/xen.h
Normal file
|
@ -0,0 +1,899 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* xen.h
|
||||||
|
*
|
||||||
|
* Guest OS interface to Xen.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to
|
||||||
|
* deal in the Software without restriction, including without limitation the
|
||||||
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
* sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2004, K A Fraser
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __XEN_PUBLIC_XEN_H__
|
||||||
|
#define __XEN_PUBLIC_XEN_H__
|
||||||
|
|
||||||
|
#include "xen-compat.h"
|
||||||
|
|
||||||
|
#if defined(__i386__) || defined(__x86_64__)
|
||||||
|
#include "arch-x86/xen.h"
|
||||||
|
#elif defined(__arm__) || defined (__aarch64__)
|
||||||
|
#include "arch-arm.h"
|
||||||
|
#else
|
||||||
|
#error "Unsupported architecture"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __ASSEMBLY__
|
||||||
|
/* Guest handles for primitive C types. */
|
||||||
|
DEFINE_XEN_GUEST_HANDLE(char);
|
||||||
|
__DEFINE_XEN_GUEST_HANDLE(uchar, unsigned char);
|
||||||
|
DEFINE_XEN_GUEST_HANDLE(int);
|
||||||
|
__DEFINE_XEN_GUEST_HANDLE(uint, unsigned int);
|
||||||
|
#if __XEN_INTERFACE_VERSION__ < 0x00040300
|
||||||
|
DEFINE_XEN_GUEST_HANDLE(long);
|
||||||
|
__DEFINE_XEN_GUEST_HANDLE(ulong, unsigned long);
|
||||||
|
#endif
|
||||||
|
DEFINE_XEN_GUEST_HANDLE(void);
|
||||||
|
|
||||||
|
DEFINE_XEN_GUEST_HANDLE(uint64_t);
|
||||||
|
DEFINE_XEN_GUEST_HANDLE(xen_pfn_t);
|
||||||
|
DEFINE_XEN_GUEST_HANDLE(xen_ulong_t);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* HYPERCALLS
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* `incontents 100 hcalls List of hypercalls
|
||||||
|
* ` enum hypercall_num { // __HYPERVISOR_* => HYPERVISOR_*()
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define __HYPERVISOR_set_trap_table 0
|
||||||
|
#define __HYPERVISOR_mmu_update 1
|
||||||
|
#define __HYPERVISOR_set_gdt 2
|
||||||
|
#define __HYPERVISOR_stack_switch 3
|
||||||
|
#define __HYPERVISOR_set_callbacks 4
|
||||||
|
#define __HYPERVISOR_fpu_taskswitch 5
|
||||||
|
#define __HYPERVISOR_sched_op_compat 6 /* compat since 0x00030101 */
|
||||||
|
#define __HYPERVISOR_platform_op 7
|
||||||
|
#define __HYPERVISOR_set_debugreg 8
|
||||||
|
#define __HYPERVISOR_get_debugreg 9
|
||||||
|
#define __HYPERVISOR_update_descriptor 10
|
||||||
|
#define __HYPERVISOR_memory_op 12
|
||||||
|
#define __HYPERVISOR_multicall 13
|
||||||
|
#define __HYPERVISOR_update_va_mapping 14
|
||||||
|
#define __HYPERVISOR_set_timer_op 15
|
||||||
|
#define __HYPERVISOR_event_channel_op_compat 16 /* compat since 0x00030202 */
|
||||||
|
#define __HYPERVISOR_xen_version 17
|
||||||
|
#define __HYPERVISOR_console_io 18
|
||||||
|
#define __HYPERVISOR_physdev_op_compat 19 /* compat since 0x00030202 */
|
||||||
|
#define __HYPERVISOR_grant_table_op 20
|
||||||
|
#define __HYPERVISOR_vm_assist 21
|
||||||
|
#define __HYPERVISOR_update_va_mapping_otherdomain 22
|
||||||
|
#define __HYPERVISOR_iret 23 /* x86 only */
|
||||||
|
#define __HYPERVISOR_vcpu_op 24
|
||||||
|
#define __HYPERVISOR_set_segment_base 25 /* x86/64 only */
|
||||||
|
#define __HYPERVISOR_mmuext_op 26
|
||||||
|
#define __HYPERVISOR_xsm_op 27
|
||||||
|
#define __HYPERVISOR_nmi_op 28
|
||||||
|
#define __HYPERVISOR_sched_op 29
|
||||||
|
#define __HYPERVISOR_callback_op 30
|
||||||
|
#define __HYPERVISOR_xenoprof_op 31
|
||||||
|
#define __HYPERVISOR_event_channel_op 32
|
||||||
|
#define __HYPERVISOR_physdev_op 33
|
||||||
|
#define __HYPERVISOR_hvm_op 34
|
||||||
|
#define __HYPERVISOR_sysctl 35
|
||||||
|
#define __HYPERVISOR_domctl 36
|
||||||
|
#define __HYPERVISOR_kexec_op 37
|
||||||
|
#define __HYPERVISOR_tmem_op 38
|
||||||
|
#define __HYPERVISOR_xc_reserved_op 39 /* reserved for XenClient */
|
||||||
|
|
||||||
|
/* Architecture-specific hypercall definitions. */
|
||||||
|
#define __HYPERVISOR_arch_0 48
|
||||||
|
#define __HYPERVISOR_arch_1 49
|
||||||
|
#define __HYPERVISOR_arch_2 50
|
||||||
|
#define __HYPERVISOR_arch_3 51
|
||||||
|
#define __HYPERVISOR_arch_4 52
|
||||||
|
#define __HYPERVISOR_arch_5 53
|
||||||
|
#define __HYPERVISOR_arch_6 54
|
||||||
|
#define __HYPERVISOR_arch_7 55
|
||||||
|
|
||||||
|
/* ` } */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* HYPERCALL COMPATIBILITY.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* New sched_op hypercall introduced in 0x00030101. */
|
||||||
|
#if __XEN_INTERFACE_VERSION__ < 0x00030101
|
||||||
|
#undef __HYPERVISOR_sched_op
|
||||||
|
#define __HYPERVISOR_sched_op __HYPERVISOR_sched_op_compat
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* New event-channel and physdev hypercalls introduced in 0x00030202. */
|
||||||
|
#if __XEN_INTERFACE_VERSION__ < 0x00030202
|
||||||
|
#undef __HYPERVISOR_event_channel_op
|
||||||
|
#define __HYPERVISOR_event_channel_op __HYPERVISOR_event_channel_op_compat
|
||||||
|
#undef __HYPERVISOR_physdev_op
|
||||||
|
#define __HYPERVISOR_physdev_op __HYPERVISOR_physdev_op_compat
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* New platform_op hypercall introduced in 0x00030204. */
|
||||||
|
#if __XEN_INTERFACE_VERSION__ < 0x00030204
|
||||||
|
#define __HYPERVISOR_dom0_op __HYPERVISOR_platform_op
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* VIRTUAL INTERRUPTS
|
||||||
|
*
|
||||||
|
* Virtual interrupts that a guest OS may receive from Xen.
|
||||||
|
*
|
||||||
|
* In the side comments, 'V.' denotes a per-VCPU VIRQ while 'G.' denotes a
|
||||||
|
* global VIRQ. The former can be bound once per VCPU and cannot be re-bound.
|
||||||
|
* The latter can be allocated only once per guest: they must initially be
|
||||||
|
* allocated to VCPU0 but can subsequently be re-bound.
|
||||||
|
*/
|
||||||
|
/* ` enum virq { */
|
||||||
|
#define VIRQ_TIMER 0 /* V. Timebase update, and/or requested timeout. */
|
||||||
|
#define VIRQ_DEBUG 1 /* V. Request guest to dump debug info. */
|
||||||
|
#define VIRQ_CONSOLE 2 /* G. (DOM0) Bytes received on emergency console. */
|
||||||
|
#define VIRQ_DOM_EXC 3 /* G. (DOM0) Exceptional event for some domain. */
|
||||||
|
#define VIRQ_TBUF 4 /* G. (DOM0) Trace buffer has records available. */
|
||||||
|
#define VIRQ_DEBUGGER 6 /* G. (DOM0) A domain has paused for debugging. */
|
||||||
|
#define VIRQ_XENOPROF 7 /* V. XenOprofile interrupt: new sample available */
|
||||||
|
#define VIRQ_CON_RING 8 /* G. (DOM0) Bytes received on console */
|
||||||
|
#define VIRQ_PCPU_STATE 9 /* G. (DOM0) PCPU state changed */
|
||||||
|
#define VIRQ_MEM_EVENT 10 /* G. (DOM0) A memory event has occured */
|
||||||
|
#define VIRQ_XC_RESERVED 11 /* G. Reserved for XenClient */
|
||||||
|
#define VIRQ_ENOMEM 12 /* G. (DOM0) Low on heap memory */
|
||||||
|
|
||||||
|
/* Architecture-specific VIRQ definitions. */
|
||||||
|
#define VIRQ_ARCH_0 16
|
||||||
|
#define VIRQ_ARCH_1 17
|
||||||
|
#define VIRQ_ARCH_2 18
|
||||||
|
#define VIRQ_ARCH_3 19
|
||||||
|
#define VIRQ_ARCH_4 20
|
||||||
|
#define VIRQ_ARCH_5 21
|
||||||
|
#define VIRQ_ARCH_6 22
|
||||||
|
#define VIRQ_ARCH_7 23
|
||||||
|
/* ` } */
|
||||||
|
|
||||||
|
#define NR_VIRQS 24
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ` enum neg_errnoval
|
||||||
|
* ` HYPERVISOR_mmu_update(const struct mmu_update reqs[],
|
||||||
|
* ` unsigned count, unsigned *done_out,
|
||||||
|
* ` unsigned foreigndom)
|
||||||
|
* `
|
||||||
|
* @reqs is an array of mmu_update_t structures ((ptr, val) pairs).
|
||||||
|
* @count is the length of the above array.
|
||||||
|
* @pdone is an output parameter indicating number of completed operations
|
||||||
|
* @foreigndom[15:0]: FD, the expected owner of data pages referenced in this
|
||||||
|
* hypercall invocation. Can be DOMID_SELF.
|
||||||
|
* @foreigndom[31:16]: PFD, the expected owner of pagetable pages referenced
|
||||||
|
* in this hypercall invocation. The value of this field
|
||||||
|
* (x) encodes the PFD as follows:
|
||||||
|
* x == 0 => PFD == DOMID_SELF
|
||||||
|
* x != 0 => PFD == x - 1
|
||||||
|
*
|
||||||
|
* Sub-commands: ptr[1:0] specifies the appropriate MMU_* command.
|
||||||
|
* -------------
|
||||||
|
* ptr[1:0] == MMU_NORMAL_PT_UPDATE:
|
||||||
|
* Updates an entry in a page table belonging to PFD. If updating an L1 table,
|
||||||
|
* and the new table entry is valid/present, the mapped frame must belong to
|
||||||
|
* FD. If attempting to map an I/O page then the caller assumes the privilege
|
||||||
|
* of the FD.
|
||||||
|
* FD == DOMID_IO: Permit /only/ I/O mappings, at the priv level of the caller.
|
||||||
|
* FD == DOMID_XEN: Map restricted areas of Xen's heap space.
|
||||||
|
* ptr[:2] -- Machine address of the page-table entry to modify.
|
||||||
|
* val -- Value to write.
|
||||||
|
*
|
||||||
|
* There also certain implicit requirements when using this hypercall. The
|
||||||
|
* pages that make up a pagetable must be mapped read-only in the guest.
|
||||||
|
* This prevents uncontrolled guest updates to the pagetable. Xen strictly
|
||||||
|
* enforces this, and will disallow any pagetable update which will end up
|
||||||
|
* mapping pagetable page RW, and will disallow using any writable page as a
|
||||||
|
* pagetable. In practice it means that when constructing a page table for a
|
||||||
|
* process, thread, etc, we MUST be very dilligient in following these rules:
|
||||||
|
* 1). Start with top-level page (PGD or in Xen language: L4). Fill out
|
||||||
|
* the entries.
|
||||||
|
* 2). Keep on going, filling out the upper (PUD or L3), and middle (PMD
|
||||||
|
* or L2).
|
||||||
|
* 3). Start filling out the PTE table (L1) with the PTE entries. Once
|
||||||
|
* done, make sure to set each of those entries to RO (so writeable bit
|
||||||
|
* is unset). Once that has been completed, set the PMD (L2) for this
|
||||||
|
* PTE table as RO.
|
||||||
|
* 4). When completed with all of the PMD (L2) entries, and all of them have
|
||||||
|
* been set to RO, make sure to set RO the PUD (L3). Do the same
|
||||||
|
* operation on PGD (L4) pagetable entries that have a PUD (L3) entry.
|
||||||
|
* 5). Now before you can use those pages (so setting the cr3), you MUST also
|
||||||
|
* pin them so that the hypervisor can verify the entries. This is done
|
||||||
|
* via the HYPERVISOR_mmuext_op(MMUEXT_PIN_L4_TABLE, guest physical frame
|
||||||
|
* number of the PGD (L4)). And this point the HYPERVISOR_mmuext_op(
|
||||||
|
* MMUEXT_NEW_BASEPTR, guest physical frame number of the PGD (L4)) can be
|
||||||
|
* issued.
|
||||||
|
* For 32-bit guests, the L4 is not used (as there is less pagetables), so
|
||||||
|
* instead use L3.
|
||||||
|
* At this point the pagetables can be modified using the MMU_NORMAL_PT_UPDATE
|
||||||
|
* hypercall. Also if so desired the OS can also try to write to the PTE
|
||||||
|
* and be trapped by the hypervisor (as the PTE entry is RO).
|
||||||
|
*
|
||||||
|
* To deallocate the pages, the operations are the reverse of the steps
|
||||||
|
* mentioned above. The argument is MMUEXT_UNPIN_TABLE for all levels and the
|
||||||
|
* pagetable MUST not be in use (meaning that the cr3 is not set to it).
|
||||||
|
*
|
||||||
|
* ptr[1:0] == MMU_MACHPHYS_UPDATE:
|
||||||
|
* Updates an entry in the machine->pseudo-physical mapping table.
|
||||||
|
* ptr[:2] -- Machine address within the frame whose mapping to modify.
|
||||||
|
* The frame must belong to the FD, if one is specified.
|
||||||
|
* val -- Value to write into the mapping entry.
|
||||||
|
*
|
||||||
|
* ptr[1:0] == MMU_PT_UPDATE_PRESERVE_AD:
|
||||||
|
* As MMU_NORMAL_PT_UPDATE above, but A/D bits currently in the PTE are ORed
|
||||||
|
* with those in @val.
|
||||||
|
*
|
||||||
|
* @val is usually the machine frame number along with some attributes.
|
||||||
|
* The attributes by default follow the architecture defined bits. Meaning that
|
||||||
|
* if this is a X86_64 machine and four page table layout is used, the layout
|
||||||
|
* of val is:
|
||||||
|
* - 63 if set means No execute (NX)
|
||||||
|
* - 46-13 the machine frame number
|
||||||
|
* - 12 available for guest
|
||||||
|
* - 11 available for guest
|
||||||
|
* - 10 available for guest
|
||||||
|
* - 9 available for guest
|
||||||
|
* - 8 global
|
||||||
|
* - 7 PAT (PSE is disabled, must use hypercall to make 4MB or 2MB pages)
|
||||||
|
* - 6 dirty
|
||||||
|
* - 5 accessed
|
||||||
|
* - 4 page cached disabled
|
||||||
|
* - 3 page write through
|
||||||
|
* - 2 userspace accessible
|
||||||
|
* - 1 writeable
|
||||||
|
* - 0 present
|
||||||
|
*
|
||||||
|
* The one bits that does not fit with the default layout is the PAGE_PSE
|
||||||
|
* also called PAGE_PAT). The MMUEXT_[UN]MARK_SUPER arguments to the
|
||||||
|
* HYPERVISOR_mmuext_op serve as mechanism to set a pagetable to be 4MB
|
||||||
|
* (or 2MB) instead of using the PAGE_PSE bit.
|
||||||
|
*
|
||||||
|
* The reason that the PAGE_PSE (bit 7) is not being utilized is due to Xen
|
||||||
|
* using it as the Page Attribute Table (PAT) bit - for details on it please
|
||||||
|
* refer to Intel SDM 10.12. The PAT allows to set the caching attributes of
|
||||||
|
* pages instead of using MTRRs.
|
||||||
|
*
|
||||||
|
* The PAT MSR is as follows (it is a 64-bit value, each entry is 8 bits):
|
||||||
|
* PAT4 PAT0
|
||||||
|
* +-----+-----+----+----+----+-----+----+----+
|
||||||
|
* | UC | UC- | WC | WB | UC | UC- | WC | WB | <= Linux
|
||||||
|
* +-----+-----+----+----+----+-----+----+----+
|
||||||
|
* | UC | UC- | WT | WB | UC | UC- | WT | WB | <= BIOS (default when machine boots)
|
||||||
|
* +-----+-----+----+----+----+-----+----+----+
|
||||||
|
* | rsv | rsv | WP | WC | UC | UC- | WT | WB | <= Xen
|
||||||
|
* +-----+-----+----+----+----+-----+----+----+
|
||||||
|
*
|
||||||
|
* The lookup of this index table translates to looking up
|
||||||
|
* Bit 7, Bit 4, and Bit 3 of val entry:
|
||||||
|
*
|
||||||
|
* PAT/PSE (bit 7) ... PCD (bit 4) .. PWT (bit 3).
|
||||||
|
*
|
||||||
|
* If all bits are off, then we are using PAT0. If bit 3 turned on,
|
||||||
|
* then we are using PAT1, if bit 3 and bit 4, then PAT2..
|
||||||
|
*
|
||||||
|
* As you can see, the Linux PAT1 translates to PAT4 under Xen. Which means
|
||||||
|
* that if a guest that follows Linux's PAT setup and would like to set Write
|
||||||
|
* Combined on pages it MUST use PAT4 entry. Meaning that Bit 7 (PAGE_PAT) is
|
||||||
|
* set. For example, under Linux it only uses PAT0, PAT1, and PAT2 for the
|
||||||
|
* caching as:
|
||||||
|
*
|
||||||
|
* WB = none (so PAT0)
|
||||||
|
* WC = PWT (bit 3 on)
|
||||||
|
* UC = PWT | PCD (bit 3 and 4 are on).
|
||||||
|
*
|
||||||
|
* To make it work with Xen, it needs to translate the WC bit as so:
|
||||||
|
*
|
||||||
|
* PWT (so bit 3 on) --> PAT (so bit 7 is on) and clear bit 3
|
||||||
|
*
|
||||||
|
* And to translate back it would:
|
||||||
|
*
|
||||||
|
* PAT (bit 7 on) --> PWT (bit 3 on) and clear bit 7.
|
||||||
|
*/
|
||||||
|
#define MMU_NORMAL_PT_UPDATE 0 /* checked '*ptr = val'. ptr is MA. */
|
||||||
|
#define MMU_MACHPHYS_UPDATE 1 /* ptr = MA of frame to modify entry for */
|
||||||
|
#define MMU_PT_UPDATE_PRESERVE_AD 2 /* atomically: *ptr = val | (*ptr&(A|D)) */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MMU EXTENDED OPERATIONS
|
||||||
|
*
|
||||||
|
* ` enum neg_errnoval
|
||||||
|
* ` HYPERVISOR_mmuext_op(mmuext_op_t uops[],
|
||||||
|
* ` unsigned int count,
|
||||||
|
* ` unsigned int *pdone,
|
||||||
|
* ` unsigned int foreigndom)
|
||||||
|
*/
|
||||||
|
/* HYPERVISOR_mmuext_op() accepts a list of mmuext_op structures.
|
||||||
|
* A foreigndom (FD) can be specified (or DOMID_SELF for none).
|
||||||
|
* Where the FD has some effect, it is described below.
|
||||||
|
*
|
||||||
|
* cmd: MMUEXT_(UN)PIN_*_TABLE
|
||||||
|
* mfn: Machine frame number to be (un)pinned as a p.t. page.
|
||||||
|
* The frame must belong to the FD, if one is specified.
|
||||||
|
*
|
||||||
|
* cmd: MMUEXT_NEW_BASEPTR
|
||||||
|
* mfn: Machine frame number of new page-table base to install in MMU.
|
||||||
|
*
|
||||||
|
* cmd: MMUEXT_NEW_USER_BASEPTR [x86/64 only]
|
||||||
|
* mfn: Machine frame number of new page-table base to install in MMU
|
||||||
|
* when in user space.
|
||||||
|
*
|
||||||
|
* cmd: MMUEXT_TLB_FLUSH_LOCAL
|
||||||
|
* No additional arguments. Flushes local TLB.
|
||||||
|
*
|
||||||
|
* cmd: MMUEXT_INVLPG_LOCAL
|
||||||
|
* linear_addr: Linear address to be flushed from the local TLB.
|
||||||
|
*
|
||||||
|
* cmd: MMUEXT_TLB_FLUSH_MULTI
|
||||||
|
* vcpumask: Pointer to bitmap of VCPUs to be flushed.
|
||||||
|
*
|
||||||
|
* cmd: MMUEXT_INVLPG_MULTI
|
||||||
|
* linear_addr: Linear address to be flushed.
|
||||||
|
* vcpumask: Pointer to bitmap of VCPUs to be flushed.
|
||||||
|
*
|
||||||
|
* cmd: MMUEXT_TLB_FLUSH_ALL
|
||||||
|
* No additional arguments. Flushes all VCPUs' TLBs.
|
||||||
|
*
|
||||||
|
* cmd: MMUEXT_INVLPG_ALL
|
||||||
|
* linear_addr: Linear address to be flushed from all VCPUs' TLBs.
|
||||||
|
*
|
||||||
|
* cmd: MMUEXT_FLUSH_CACHE
|
||||||
|
* No additional arguments. Writes back and flushes cache contents.
|
||||||
|
*
|
||||||
|
* cmd: MMUEXT_FLUSH_CACHE_GLOBAL
|
||||||
|
* No additional arguments. Writes back and flushes cache contents
|
||||||
|
* on all CPUs in the system.
|
||||||
|
*
|
||||||
|
* cmd: MMUEXT_SET_LDT
|
||||||
|
* linear_addr: Linear address of LDT base (NB. must be page-aligned).
|
||||||
|
* nr_ents: Number of entries in LDT.
|
||||||
|
*
|
||||||
|
* cmd: MMUEXT_CLEAR_PAGE
|
||||||
|
* mfn: Machine frame number to be cleared.
|
||||||
|
*
|
||||||
|
* cmd: MMUEXT_COPY_PAGE
|
||||||
|
* mfn: Machine frame number of the destination page.
|
||||||
|
* src_mfn: Machine frame number of the source page.
|
||||||
|
*
|
||||||
|
* cmd: MMUEXT_[UN]MARK_SUPER
|
||||||
|
* mfn: Machine frame number of head of superpage to be [un]marked.
|
||||||
|
*/
|
||||||
|
/* ` enum mmuext_cmd { */
|
||||||
|
#define MMUEXT_PIN_L1_TABLE 0
|
||||||
|
#define MMUEXT_PIN_L2_TABLE 1
|
||||||
|
#define MMUEXT_PIN_L3_TABLE 2
|
||||||
|
#define MMUEXT_PIN_L4_TABLE 3
|
||||||
|
#define MMUEXT_UNPIN_TABLE 4
|
||||||
|
#define MMUEXT_NEW_BASEPTR 5
|
||||||
|
#define MMUEXT_TLB_FLUSH_LOCAL 6
|
||||||
|
#define MMUEXT_INVLPG_LOCAL 7
|
||||||
|
#define MMUEXT_TLB_FLUSH_MULTI 8
|
||||||
|
#define MMUEXT_INVLPG_MULTI 9
|
||||||
|
#define MMUEXT_TLB_FLUSH_ALL 10
|
||||||
|
#define MMUEXT_INVLPG_ALL 11
|
||||||
|
#define MMUEXT_FLUSH_CACHE 12
|
||||||
|
#define MMUEXT_SET_LDT 13
|
||||||
|
#define MMUEXT_NEW_USER_BASEPTR 15
|
||||||
|
#define MMUEXT_CLEAR_PAGE 16
|
||||||
|
#define MMUEXT_COPY_PAGE 17
|
||||||
|
#define MMUEXT_FLUSH_CACHE_GLOBAL 18
|
||||||
|
#define MMUEXT_MARK_SUPER 19
|
||||||
|
#define MMUEXT_UNMARK_SUPER 20
|
||||||
|
/* ` } */
|
||||||
|
|
||||||
|
#ifndef __ASSEMBLY__
|
||||||
|
struct mmuext_op {
|
||||||
|
unsigned int cmd; /* => enum mmuext_cmd */
|
||||||
|
union {
|
||||||
|
/* [UN]PIN_TABLE, NEW_BASEPTR, NEW_USER_BASEPTR
|
||||||
|
* CLEAR_PAGE, COPY_PAGE, [UN]MARK_SUPER */
|
||||||
|
xen_pfn_t mfn;
|
||||||
|
/* INVLPG_LOCAL, INVLPG_ALL, SET_LDT */
|
||||||
|
unsigned long linear_addr;
|
||||||
|
} arg1;
|
||||||
|
union {
|
||||||
|
/* SET_LDT */
|
||||||
|
unsigned int nr_ents;
|
||||||
|
/* TLB_FLUSH_MULTI, INVLPG_MULTI */
|
||||||
|
#if __XEN_INTERFACE_VERSION__ >= 0x00030205
|
||||||
|
XEN_GUEST_HANDLE(const_void) vcpumask;
|
||||||
|
#else
|
||||||
|
const void *vcpumask;
|
||||||
|
#endif
|
||||||
|
/* COPY_PAGE */
|
||||||
|
xen_pfn_t src_mfn;
|
||||||
|
} arg2;
|
||||||
|
};
|
||||||
|
typedef struct mmuext_op mmuext_op_t;
|
||||||
|
DEFINE_XEN_GUEST_HANDLE(mmuext_op_t);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ` enum neg_errnoval
|
||||||
|
* ` HYPERVISOR_update_va_mapping(unsigned long va, u64 val,
|
||||||
|
* ` enum uvm_flags flags)
|
||||||
|
* `
|
||||||
|
* ` enum neg_errnoval
|
||||||
|
* ` HYPERVISOR_update_va_mapping_otherdomain(unsigned long va, u64 val,
|
||||||
|
* ` enum uvm_flags flags,
|
||||||
|
* ` domid_t domid)
|
||||||
|
* `
|
||||||
|
* ` @va: The virtual address whose mapping we want to change
|
||||||
|
* ` @val: The new page table entry, must contain a machine address
|
||||||
|
* ` @flags: Control TLB flushes
|
||||||
|
*/
|
||||||
|
/* These are passed as 'flags' to update_va_mapping. They can be ORed. */
|
||||||
|
/* When specifying UVMF_MULTI, also OR in a pointer to a CPU bitmap. */
|
||||||
|
/* UVMF_LOCAL is merely UVMF_MULTI with a NULL bitmap pointer. */
|
||||||
|
/* ` enum uvm_flags { */
|
||||||
|
#define UVMF_NONE (0UL<<0) /* No flushing at all. */
|
||||||
|
#define UVMF_TLB_FLUSH (1UL<<0) /* Flush entire TLB(s). */
|
||||||
|
#define UVMF_INVLPG (2UL<<0) /* Flush only one entry. */
|
||||||
|
#define UVMF_FLUSHTYPE_MASK (3UL<<0)
|
||||||
|
#define UVMF_MULTI (0UL<<2) /* Flush subset of TLBs. */
|
||||||
|
#define UVMF_LOCAL (0UL<<2) /* Flush local TLB. */
|
||||||
|
#define UVMF_ALL (1UL<<2) /* Flush all TLBs. */
|
||||||
|
/* ` } */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Commands to HYPERVISOR_console_io().
|
||||||
|
*/
|
||||||
|
#define CONSOLEIO_write 0
|
||||||
|
#define CONSOLEIO_read 1
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Commands to HYPERVISOR_vm_assist().
|
||||||
|
*/
|
||||||
|
#define VMASST_CMD_enable 0
|
||||||
|
#define VMASST_CMD_disable 1
|
||||||
|
|
||||||
|
/* x86/32 guests: simulate full 4GB segment limits. */
|
||||||
|
#define VMASST_TYPE_4gb_segments 0
|
||||||
|
|
||||||
|
/* x86/32 guests: trap (vector 15) whenever above vmassist is used. */
|
||||||
|
#define VMASST_TYPE_4gb_segments_notify 1
|
||||||
|
|
||||||
|
/*
|
||||||
|
* x86 guests: support writes to bottom-level PTEs.
|
||||||
|
* NB1. Page-directory entries cannot be written.
|
||||||
|
* NB2. Guest must continue to remove all writable mappings of PTEs.
|
||||||
|
*/
|
||||||
|
#define VMASST_TYPE_writable_pagetables 2
|
||||||
|
|
||||||
|
/* x86/PAE guests: support PDPTs above 4GB. */
|
||||||
|
#define VMASST_TYPE_pae_extended_cr3 3
|
||||||
|
|
||||||
|
#define MAX_VMASST_TYPE 3
|
||||||
|
|
||||||
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
|
typedef uint16_t domid_t;
|
||||||
|
|
||||||
|
/* Domain ids >= DOMID_FIRST_RESERVED cannot be used for ordinary domains. */
|
||||||
|
#define DOMID_FIRST_RESERVED (0x7FF0U)
|
||||||
|
|
||||||
|
/* DOMID_SELF is used in certain contexts to refer to oneself. */
|
||||||
|
#define DOMID_SELF (0x7FF0U)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DOMID_IO is used to restrict page-table updates to mapping I/O memory.
|
||||||
|
* Although no Foreign Domain need be specified to map I/O pages, DOMID_IO
|
||||||
|
* is useful to ensure that no mappings to the OS's own heap are accidentally
|
||||||
|
* installed. (e.g., in Linux this could cause havoc as reference counts
|
||||||
|
* aren't adjusted on the I/O-mapping code path).
|
||||||
|
* This only makes sense in MMUEXT_SET_FOREIGNDOM, but in that context can
|
||||||
|
* be specified by any calling domain.
|
||||||
|
*/
|
||||||
|
#define DOMID_IO (0x7FF1U)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DOMID_XEN is used to allow privileged domains to map restricted parts of
|
||||||
|
* Xen's heap space (e.g., the machine_to_phys table).
|
||||||
|
* This only makes sense in MMUEXT_SET_FOREIGNDOM, and is only permitted if
|
||||||
|
* the caller is privileged.
|
||||||
|
*/
|
||||||
|
#define DOMID_XEN (0x7FF2U)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DOMID_COW is used as the owner of sharable pages */
|
||||||
|
#define DOMID_COW (0x7FF3U)
|
||||||
|
|
||||||
|
/* DOMID_INVALID is used to identify pages with unknown owner. */
|
||||||
|
#define DOMID_INVALID (0x7FF4U)
|
||||||
|
|
||||||
|
/* Idle domain. */
|
||||||
|
#define DOMID_IDLE (0x7FFFU)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Send an array of these to HYPERVISOR_mmu_update().
|
||||||
|
* NB. The fields are natural pointer/address size for this architecture.
|
||||||
|
*/
|
||||||
|
struct mmu_update {
|
||||||
|
uint64_t ptr; /* Machine address of PTE. */
|
||||||
|
uint64_t val; /* New contents of PTE. */
|
||||||
|
};
|
||||||
|
typedef struct mmu_update mmu_update_t;
|
||||||
|
DEFINE_XEN_GUEST_HANDLE(mmu_update_t);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ` enum neg_errnoval
|
||||||
|
* ` HYPERVISOR_multicall(multicall_entry_t call_list[],
|
||||||
|
* ` uint32_t nr_calls);
|
||||||
|
*
|
||||||
|
* NB. The fields are logically the natural register size for this
|
||||||
|
* architecture. In cases where xen_ulong_t is larger than this then
|
||||||
|
* any unused bits in the upper portion must be zero.
|
||||||
|
*/
|
||||||
|
struct multicall_entry {
|
||||||
|
xen_ulong_t op, result;
|
||||||
|
xen_ulong_t args[6];
|
||||||
|
};
|
||||||
|
typedef struct multicall_entry multicall_entry_t;
|
||||||
|
DEFINE_XEN_GUEST_HANDLE(multicall_entry_t);
|
||||||
|
|
||||||
|
#if __XEN_INTERFACE_VERSION__ < 0x00040400
|
||||||
|
/*
|
||||||
|
* Event channel endpoints per domain (when using the 2-level ABI):
|
||||||
|
* 1024 if a long is 32 bits; 4096 if a long is 64 bits.
|
||||||
|
*/
|
||||||
|
#define NR_EVENT_CHANNELS EVTCHN_2L_NR_CHANNELS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct vcpu_time_info {
|
||||||
|
/*
|
||||||
|
* Updates to the following values are preceded and followed by an
|
||||||
|
* increment of 'version'. The guest can therefore detect updates by
|
||||||
|
* looking for changes to 'version'. If the least-significant bit of
|
||||||
|
* the version number is set then an update is in progress and the guest
|
||||||
|
* must wait to read a consistent set of values.
|
||||||
|
* The correct way to interact with the version number is similar to
|
||||||
|
* Linux's seqlock: see the implementations of read_seqbegin/read_seqretry.
|
||||||
|
*/
|
||||||
|
uint32_t version;
|
||||||
|
uint32_t pad0;
|
||||||
|
uint64_t tsc_timestamp; /* TSC at last update of time vals. */
|
||||||
|
uint64_t system_time; /* Time, in nanosecs, since boot. */
|
||||||
|
/*
|
||||||
|
* Current system time:
|
||||||
|
* system_time +
|
||||||
|
* ((((tsc - tsc_timestamp) << tsc_shift) * tsc_to_system_mul) >> 32)
|
||||||
|
* CPU frequency (Hz):
|
||||||
|
* ((10^9 << 32) / tsc_to_system_mul) >> tsc_shift
|
||||||
|
*/
|
||||||
|
uint32_t tsc_to_system_mul;
|
||||||
|
int8_t tsc_shift;
|
||||||
|
int8_t pad1[3];
|
||||||
|
}; /* 32 bytes */
|
||||||
|
typedef struct vcpu_time_info vcpu_time_info_t;
|
||||||
|
|
||||||
|
struct vcpu_info {
|
||||||
|
/*
|
||||||
|
* 'evtchn_upcall_pending' is written non-zero by Xen to indicate
|
||||||
|
* a pending notification for a particular VCPU. It is then cleared
|
||||||
|
* by the guest OS /before/ checking for pending work, thus avoiding
|
||||||
|
* a set-and-check race. Note that the mask is only accessed by Xen
|
||||||
|
* on the CPU that is currently hosting the VCPU. This means that the
|
||||||
|
* pending and mask flags can be updated by the guest without special
|
||||||
|
* synchronisation (i.e., no need for the x86 LOCK prefix).
|
||||||
|
* This may seem suboptimal because if the pending flag is set by
|
||||||
|
* a different CPU then an IPI may be scheduled even when the mask
|
||||||
|
* is set. However, note:
|
||||||
|
* 1. The task of 'interrupt holdoff' is covered by the per-event-
|
||||||
|
* channel mask bits. A 'noisy' event that is continually being
|
||||||
|
* triggered can be masked at source at this very precise
|
||||||
|
* granularity.
|
||||||
|
* 2. The main purpose of the per-VCPU mask is therefore to restrict
|
||||||
|
* reentrant execution: whether for concurrency control, or to
|
||||||
|
* prevent unbounded stack usage. Whatever the purpose, we expect
|
||||||
|
* that the mask will be asserted only for short periods at a time,
|
||||||
|
* and so the likelihood of a 'spurious' IPI is suitably small.
|
||||||
|
* The mask is read before making an event upcall to the guest: a
|
||||||
|
* non-zero mask therefore guarantees that the VCPU will not receive
|
||||||
|
* an upcall activation. The mask is cleared when the VCPU requests
|
||||||
|
* to block: this avoids wakeup-waiting races.
|
||||||
|
*/
|
||||||
|
uint8_t evtchn_upcall_pending;
|
||||||
|
#ifdef XEN_HAVE_PV_UPCALL_MASK
|
||||||
|
uint8_t evtchn_upcall_mask;
|
||||||
|
#else /* XEN_HAVE_PV_UPCALL_MASK */
|
||||||
|
uint8_t pad0;
|
||||||
|
#endif /* XEN_HAVE_PV_UPCALL_MASK */
|
||||||
|
xen_ulong_t evtchn_pending_sel;
|
||||||
|
struct arch_vcpu_info arch;
|
||||||
|
struct vcpu_time_info time;
|
||||||
|
}; /* 64 bytes (x86) */
|
||||||
|
#ifndef __XEN__
|
||||||
|
typedef struct vcpu_info vcpu_info_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* `incontents 200 startofday_shared Start-of-day shared data structure
|
||||||
|
* Xen/kernel shared data -- pointer provided in start_info.
|
||||||
|
*
|
||||||
|
* This structure is defined to be both smaller than a page, and the
|
||||||
|
* only data on the shared page, but may vary in actual size even within
|
||||||
|
* compatible Xen versions; guests should not rely on the size
|
||||||
|
* of this structure remaining constant.
|
||||||
|
*/
|
||||||
|
struct shared_info {
|
||||||
|
struct vcpu_info vcpu_info[XEN_LEGACY_MAX_VCPUS];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A domain can create "event channels" on which it can send and receive
|
||||||
|
* asynchronous event notifications. There are three classes of event that
|
||||||
|
* are delivered by this mechanism:
|
||||||
|
* 1. Bi-directional inter- and intra-domain connections. Domains must
|
||||||
|
* arrange out-of-band to set up a connection (usually by allocating
|
||||||
|
* an unbound 'listener' port and avertising that via a storage service
|
||||||
|
* such as xenstore).
|
||||||
|
* 2. Physical interrupts. A domain with suitable hardware-access
|
||||||
|
* privileges can bind an event-channel port to a physical interrupt
|
||||||
|
* source.
|
||||||
|
* 3. Virtual interrupts ('events'). A domain can bind an event-channel
|
||||||
|
* port to a virtual interrupt source, such as the virtual-timer
|
||||||
|
* device or the emergency console.
|
||||||
|
*
|
||||||
|
* Event channels are addressed by a "port index". Each channel is
|
||||||
|
* associated with two bits of information:
|
||||||
|
* 1. PENDING -- notifies the domain that there is a pending notification
|
||||||
|
* to be processed. This bit is cleared by the guest.
|
||||||
|
* 2. MASK -- if this bit is clear then a 0->1 transition of PENDING
|
||||||
|
* will cause an asynchronous upcall to be scheduled. This bit is only
|
||||||
|
* updated by the guest. It is read-only within Xen. If a channel
|
||||||
|
* becomes pending while the channel is masked then the 'edge' is lost
|
||||||
|
* (i.e., when the channel is unmasked, the guest must manually handle
|
||||||
|
* pending notifications as no upcall will be scheduled by Xen).
|
||||||
|
*
|
||||||
|
* To expedite scanning of pending notifications, any 0->1 pending
|
||||||
|
* transition on an unmasked channel causes a corresponding bit in a
|
||||||
|
* per-vcpu selector word to be set. Each bit in the selector covers a
|
||||||
|
* 'C long' in the PENDING bitfield array.
|
||||||
|
*/
|
||||||
|
xen_ulong_t evtchn_pending[sizeof(xen_ulong_t) * 8];
|
||||||
|
xen_ulong_t evtchn_mask[sizeof(xen_ulong_t) * 8];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wallclock time: updated only by control software. Guests should base
|
||||||
|
* their gettimeofday() syscall on this wallclock-base value.
|
||||||
|
*/
|
||||||
|
uint32_t wc_version; /* Version counter: see vcpu_time_info_t. */
|
||||||
|
uint32_t wc_sec; /* Secs 00:00:00 UTC, Jan 1, 1970. */
|
||||||
|
uint32_t wc_nsec; /* Nsecs 00:00:00 UTC, Jan 1, 1970. */
|
||||||
|
|
||||||
|
struct arch_shared_info arch;
|
||||||
|
|
||||||
|
};
|
||||||
|
#ifndef __XEN__
|
||||||
|
typedef struct shared_info shared_info_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* `incontents 200 startofday Start-of-day memory layout
|
||||||
|
*
|
||||||
|
* 1. The domain is started within contiguous virtual-memory region.
|
||||||
|
* 2. The contiguous region ends on an aligned 4MB boundary.
|
||||||
|
* 3. This the order of bootstrap elements in the initial virtual region:
|
||||||
|
* a. relocated kernel image
|
||||||
|
* b. initial ram disk [mod_start, mod_len]
|
||||||
|
* c. list of allocated page frames [mfn_list, nr_pages]
|
||||||
|
* (unless relocated due to XEN_ELFNOTE_INIT_P2M)
|
||||||
|
* d. start_info_t structure [register ESI (x86)]
|
||||||
|
* e. bootstrap page tables [pt_base and CR3 (x86)]
|
||||||
|
* f. bootstrap stack [register ESP (x86)]
|
||||||
|
* 4. Bootstrap elements are packed together, but each is 4kB-aligned.
|
||||||
|
* 5. The initial ram disk may be omitted.
|
||||||
|
* 6. The list of page frames forms a contiguous 'pseudo-physical' memory
|
||||||
|
* layout for the domain. In particular, the bootstrap virtual-memory
|
||||||
|
* region is a 1:1 mapping to the first section of the pseudo-physical map.
|
||||||
|
* 7. All bootstrap elements are mapped read-writable for the guest OS. The
|
||||||
|
* only exception is the bootstrap page table, which is mapped read-only.
|
||||||
|
* 8. There is guaranteed to be at least 512kB padding after the final
|
||||||
|
* bootstrap element. If necessary, the bootstrap virtual region is
|
||||||
|
* extended by an extra 4MB to ensure this.
|
||||||
|
*
|
||||||
|
* Note: Prior to 25833:bb85bbccb1c9. ("x86/32-on-64 adjust Dom0 initial page
|
||||||
|
* table layout") a bug caused the pt_base (3.e above) and cr3 to not point
|
||||||
|
* to the start of the guest page tables (it was offset by two pages).
|
||||||
|
* This only manifested itself on 32-on-64 dom0 kernels and not 32-on-64 domU
|
||||||
|
* or 64-bit kernels of any colour. The page tables for a 32-on-64 dom0 got
|
||||||
|
* allocated in the order: 'first L1','first L2', 'first L3', so the offset
|
||||||
|
* to the page table base is by two pages back. The initial domain if it is
|
||||||
|
* 32-bit and runs under a 64-bit hypervisor should _NOT_ use two of the
|
||||||
|
* pages preceding pt_base and mark them as reserved/unused.
|
||||||
|
*/
|
||||||
|
#ifdef XEN_HAVE_PV_GUEST_ENTRY
|
||||||
|
struct start_info {
|
||||||
|
/* THE FOLLOWING ARE FILLED IN BOTH ON INITIAL BOOT AND ON RESUME. */
|
||||||
|
char magic[32]; /* "xen-<version>-<platform>". */
|
||||||
|
unsigned long nr_pages; /* Total pages allocated to this domain. */
|
||||||
|
unsigned long shared_info; /* MACHINE address of shared info struct. */
|
||||||
|
uint32_t flags; /* SIF_xxx flags. */
|
||||||
|
xen_pfn_t store_mfn; /* MACHINE page number of shared page. */
|
||||||
|
uint32_t store_evtchn; /* Event channel for store communication. */
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
xen_pfn_t mfn; /* MACHINE page number of console page. */
|
||||||
|
uint32_t evtchn; /* Event channel for console page. */
|
||||||
|
} domU;
|
||||||
|
struct {
|
||||||
|
uint32_t info_off; /* Offset of console_info struct. */
|
||||||
|
uint32_t info_size; /* Size of console_info struct from start.*/
|
||||||
|
} dom0;
|
||||||
|
} console;
|
||||||
|
/* THE FOLLOWING ARE ONLY FILLED IN ON INITIAL BOOT (NOT RESUME). */
|
||||||
|
unsigned long pt_base; /* VIRTUAL address of page directory. */
|
||||||
|
unsigned long nr_pt_frames; /* Number of bootstrap p.t. frames. */
|
||||||
|
unsigned long mfn_list; /* VIRTUAL address of page-frame list. */
|
||||||
|
unsigned long mod_start; /* VIRTUAL address of pre-loaded module */
|
||||||
|
/* (PFN of pre-loaded module if */
|
||||||
|
/* SIF_MOD_START_PFN set in flags). */
|
||||||
|
unsigned long mod_len; /* Size (bytes) of pre-loaded module. */
|
||||||
|
#define MAX_GUEST_CMDLINE 1024
|
||||||
|
int8_t cmd_line[MAX_GUEST_CMDLINE];
|
||||||
|
/* The pfn range here covers both page table and p->m table frames. */
|
||||||
|
unsigned long first_p2m_pfn;/* 1st pfn forming initial P->M table. */
|
||||||
|
unsigned long nr_p2m_frames;/* # of pfns forming initial P->M table. */
|
||||||
|
};
|
||||||
|
typedef struct start_info start_info_t;
|
||||||
|
|
||||||
|
/* New console union for dom0 introduced in 0x00030203. */
|
||||||
|
#if __XEN_INTERFACE_VERSION__ < 0x00030203
|
||||||
|
#define console_mfn console.domU.mfn
|
||||||
|
#define console_evtchn console.domU.evtchn
|
||||||
|
#endif
|
||||||
|
#endif /* XEN_HAVE_PV_GUEST_ENTRY */
|
||||||
|
|
||||||
|
/* These flags are passed in the 'flags' field of start_info_t. */
|
||||||
|
#define SIF_PRIVILEGED (1<<0) /* Is the domain privileged? */
|
||||||
|
#define SIF_INITDOMAIN (1<<1) /* Is this the initial control domain? */
|
||||||
|
#define SIF_MULTIBOOT_MOD (1<<2) /* Is mod_start a multiboot module? */
|
||||||
|
#define SIF_MOD_START_PFN (1<<3) /* Is mod_start a PFN? */
|
||||||
|
#define SIF_PM_MASK (0xFF<<8) /* reserve 1 byte for xen-pm options */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A multiboot module is a package containing modules very similar to a
|
||||||
|
* multiboot module array. The only differences are:
|
||||||
|
* - the array of module descriptors is by convention simply at the beginning
|
||||||
|
* of the multiboot module,
|
||||||
|
* - addresses in the module descriptors are based on the beginning of the
|
||||||
|
* multiboot module,
|
||||||
|
* - the number of modules is determined by a termination descriptor that has
|
||||||
|
* mod_start == 0.
|
||||||
|
*
|
||||||
|
* This permits to both build it statically and reference it in a configuration
|
||||||
|
* file, and let the PV guest easily rebase the addresses to virtual addresses
|
||||||
|
* and at the same time count the number of modules.
|
||||||
|
*/
|
||||||
|
struct xen_multiboot_mod_list
|
||||||
|
{
|
||||||
|
/* Address of first byte of the module */
|
||||||
|
uint32_t mod_start;
|
||||||
|
/* Address of last byte of the module (inclusive) */
|
||||||
|
uint32_t mod_end;
|
||||||
|
/* Address of zero-terminated command line */
|
||||||
|
uint32_t cmdline;
|
||||||
|
/* Unused, must be zero */
|
||||||
|
uint32_t pad;
|
||||||
|
};
|
||||||
|
/*
|
||||||
|
* `incontents 200 startofday_dom0_console Dom0_console
|
||||||
|
*
|
||||||
|
* The console structure in start_info.console.dom0
|
||||||
|
*
|
||||||
|
* This structure includes a variety of information required to
|
||||||
|
* have a working VGA/VESA console.
|
||||||
|
*/
|
||||||
|
typedef struct dom0_vga_console_info {
|
||||||
|
uint8_t video_type; /* DOM0_VGA_CONSOLE_??? */
|
||||||
|
#define XEN_VGATYPE_TEXT_MODE_3 0x03
|
||||||
|
#define XEN_VGATYPE_VESA_LFB 0x23
|
||||||
|
#define XEN_VGATYPE_EFI_LFB 0x70
|
||||||
|
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
/* Font height, in pixels. */
|
||||||
|
uint16_t font_height;
|
||||||
|
/* Cursor location (column, row). */
|
||||||
|
uint16_t cursor_x, cursor_y;
|
||||||
|
/* Number of rows and columns (dimensions in characters). */
|
||||||
|
uint16_t rows, columns;
|
||||||
|
} text_mode_3;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
/* Width and height, in pixels. */
|
||||||
|
uint16_t width, height;
|
||||||
|
/* Bytes per scan line. */
|
||||||
|
uint16_t bytes_per_line;
|
||||||
|
/* Bits per pixel. */
|
||||||
|
uint16_t bits_per_pixel;
|
||||||
|
/* LFB physical address, and size (in units of 64kB). */
|
||||||
|
uint32_t lfb_base;
|
||||||
|
uint32_t lfb_size;
|
||||||
|
/* RGB mask offsets and sizes, as defined by VBE 1.2+ */
|
||||||
|
uint8_t red_pos, red_size;
|
||||||
|
uint8_t green_pos, green_size;
|
||||||
|
uint8_t blue_pos, blue_size;
|
||||||
|
uint8_t rsvd_pos, rsvd_size;
|
||||||
|
#if __XEN_INTERFACE_VERSION__ >= 0x00030206
|
||||||
|
/* VESA capabilities (offset 0xa, VESA command 0x4f00). */
|
||||||
|
uint32_t gbl_caps;
|
||||||
|
/* Mode attributes (offset 0x0, VESA command 0x4f01). */
|
||||||
|
uint16_t mode_attrs;
|
||||||
|
#endif
|
||||||
|
} vesa_lfb;
|
||||||
|
} u;
|
||||||
|
} dom0_vga_console_info_t;
|
||||||
|
#define xen_vga_console_info dom0_vga_console_info
|
||||||
|
#define xen_vga_console_info_t dom0_vga_console_info_t
|
||||||
|
|
||||||
|
typedef uint8_t xen_domain_handle_t[16];
|
||||||
|
|
||||||
|
/* Turn a plain number into a C unsigned long constant. */
|
||||||
|
#define __mk_unsigned_long(x) x ## UL
|
||||||
|
#define mk_unsigned_long(x) __mk_unsigned_long(x)
|
||||||
|
|
||||||
|
__DEFINE_XEN_GUEST_HANDLE(uint8, uint8_t);
|
||||||
|
__DEFINE_XEN_GUEST_HANDLE(uint16, uint16_t);
|
||||||
|
__DEFINE_XEN_GUEST_HANDLE(uint32, uint32_t);
|
||||||
|
__DEFINE_XEN_GUEST_HANDLE(uint64, uint64_t);
|
||||||
|
|
||||||
|
#else /* __ASSEMBLY__ */
|
||||||
|
|
||||||
|
/* In assembly code we cannot use C numeric constant suffixes. */
|
||||||
|
#define mk_unsigned_long(x) x
|
||||||
|
|
||||||
|
#endif /* !__ASSEMBLY__ */
|
||||||
|
|
||||||
|
/* Default definitions for macros used by domctl/sysctl. */
|
||||||
|
#if defined(__XEN__) || defined(__XEN_TOOLS__)
|
||||||
|
|
||||||
|
#ifndef uint64_aligned_t
|
||||||
|
#define uint64_aligned_t uint64_t
|
||||||
|
#endif
|
||||||
|
#ifndef XEN_GUEST_HANDLE_64
|
||||||
|
#define XEN_GUEST_HANDLE_64(name) XEN_GUEST_HANDLE(name)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __ASSEMBLY__
|
||||||
|
struct xenctl_bitmap {
|
||||||
|
XEN_GUEST_HANDLE_64(uint8) bitmap;
|
||||||
|
uint32_t nr_bits;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */
|
||||||
|
|
||||||
|
#endif /* __XEN_PUBLIC_XEN_H__ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local variables:
|
||||||
|
* mode: C
|
||||||
|
* c-file-style: "BSD"
|
||||||
|
* c-basic-offset: 4
|
||||||
|
* tab-width: 4
|
||||||
|
* indent-tabs-mode: nil
|
||||||
|
* End:
|
||||||
|
*/
|
Loading…
Reference in a new issue