[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [win-pv-devel] [PATCH 09/14 v2] Add boilerplate frontend
> -----Original Message----- > From: win-pv-devel [mailto:win-pv-devel-bounces@xxxxxxxxxxxxxxxxxxxx] On > Behalf Of owen.smith@xxxxxxxxxx > Sent: 23 February 2018 14:22 > To: win-pv-devel@xxxxxxxxxxxxxxxxxxxx > Cc: Owen Smith <owen.smith@xxxxxxxxxx> > Subject: [win-pv-devel] [PATCH 09/14 v2] Add boilerplate frontend > > From: Owen Smith <owen.smith@xxxxxxxxxx> > > * Frontend is used for non-default consoles > * State changes are disabled for now, as there is insufficient > implementation to handle the state model (no evtchn/gnttab changes) > * Reads "protocol" and "name" xenstore fields > > Signed-off-by: Owen Smith <owen.smith@xxxxxxxxxx> Acked-by: Paul Durrant <paul.durrant@xxxxxxxxxx> > --- > include/xen-types.h | 55 ++ > include/xen-version.h | 37 + > include/xen-warnings.h | 42 + > include/xen.h | 45 + > include/xen/public/arch-x86/xen-x86_32.h | 169 ++++ > include/xen/public/arch-x86/xen-x86_64.h | 202 ++++ > include/xen/public/arch-x86/xen.h | 338 +++++++ > include/xen/public/errno.h | 124 +++ > include/xen/public/grant_table.h | 684 ++++++++++++++ > include/xen/public/io/console.h | 51 + > include/xen/public/io/ring.h | 326 +++++++ > include/xen/public/io/xenbus.h | 80 ++ > include/xen/public/trace.h | 337 +++++++ > include/xen/public/xen-compat.h | 44 + > include/xen/public/xen.h | 995 ++++++++++++++++++++ > include/xen/xen/errno.h | 18 + > src/xencons/fdo.c | 4 +- > src/xencons/frontend.c | 1499 > ++++++++++++++++++++++++++++++ > src/xencons/frontend.h | 68 ++ > src/xencons/pdo.c | 3 +- > vs2015/xencons/xencons.vcxproj | 1 + > vs2017/xencons/xencons.vcxproj | 1 + > 22 files changed, 5121 insertions(+), 2 deletions(-) > create mode 100755 include/xen-types.h > create mode 100755 include/xen-version.h > create mode 100755 include/xen-warnings.h > create mode 100755 include/xen.h > create mode 100755 include/xen/public/arch-x86/xen-x86_32.h > create mode 100755 include/xen/public/arch-x86/xen-x86_64.h > create mode 100755 include/xen/public/arch-x86/xen.h > create mode 100755 include/xen/public/errno.h > create mode 100755 include/xen/public/grant_table.h > create mode 100755 include/xen/public/io/console.h > create mode 100755 include/xen/public/io/ring.h > create mode 100755 include/xen/public/io/xenbus.h > create mode 100755 include/xen/public/trace.h > create mode 100755 include/xen/public/xen-compat.h > create mode 100755 include/xen/public/xen.h > create mode 100755 include/xen/xen/errno.h > create mode 100755 src/xencons/frontend.c > create mode 100755 src/xencons/frontend.h > > diff --git a/include/xen-types.h b/include/xen-types.h > new file mode 100755 > index 0000000..232d799 > --- /dev/null > +++ b/include/xen-types.h > @@ -0,0 +1,55 @@ > +/* Copyright (c) Citrix Systems Inc. > + * All rights reserved. > + * > + * Redistribution and use in source and binary forms, > + * with or without modification, are permitted provided > + * that the following conditions are met: > + * > + * * Redistributions of source code must retain the above > + * copyright notice, this list of conditions and the > + * following disclaimer. > + * * Redistributions in binary form must reproduce the above > + * copyright notice, this list of conditions and the > + * following disclaimer in the documentation and/or other > + * materials provided with the distribution. > + * > + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND > + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, > + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF > + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE > + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR > + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, > + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, > + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR > + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS > + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, > + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING > + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE > + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF > + * SUCH DAMAGE. > + */ > + > +#ifndef _XEN_TYPES_H > +#define _XEN_TYPES_H > + > +#include <ntddk.h> > + > +// Define types necessary to include xen headers > + > +typedef CHAR int8_t; > +typedef SHORT int16_t; > +typedef LONG int32_t; > +typedef LONG64 int64_t; > + > +typedef UCHAR uint8_t; > +typedef USHORT uint16_t; > +typedef ULONG uint32_t; > +typedef ULONG64 uint64_t; > + > +#define offsetof(_type, _field) FIELD_OFFSET(_type, _field) > + > +#define xen_mb() KeMemoryBarrier() > +#define xen_wmb() KeMemoryBarrier() > +#define xen_rmb() KememoryBarrier() > + > +#endif // _XEN_TYPES_H > diff --git a/include/xen-version.h b/include/xen-version.h > new file mode 100755 > index 0000000..5da4233 > --- /dev/null > +++ b/include/xen-version.h > @@ -0,0 +1,37 @@ > +/* Copyright (c) Citrix Systems Inc. > + * All rights reserved. > + * > + * Redistribution and use in source and binary forms, > + * with or without modification, are permitted provided > + * that the following conditions are met: > + * > + * * Redistributions of source code must retain the above > + * copyright notice, this list of conditions and the > + * following disclaimer. > + * * Redistributions in binary form must reproduce the above > + * copyright notice, this list of conditions and the > + * following disclaimer in the documentation and/or other > + * materials provided with the distribution. > + * > + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND > + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, > + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF > + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE > + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR > + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, > + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, > + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR > + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS > + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, > + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING > + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE > + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF > + * SUCH DAMAGE. > + */ > + > +#ifndef _XEN_VERSION_H > +#define _XEN_VERSION_H > + > +#define __XEN_INTERFACE_VERSION__ > __XEN_LATEST_INTERFACE_VERSION__ > + > +#endif // _XEN_VERSION_H > diff --git a/include/xen-warnings.h b/include/xen-warnings.h > new file mode 100755 > index 0000000..5a095b4 > --- /dev/null > +++ b/include/xen-warnings.h > @@ -0,0 +1,42 @@ > +/* Copyright (c) Citrix Systems Inc. > + * All rights reserved. > + * > + * Redistribution and use in source and binary forms, > + * with or without modification, are permitted provided > + * that the following conditions are met: > + * > + * * Redistributions of source code must retain the above > + * copyright notice, this list of conditions and the > + * following disclaimer. > + * * Redistributions in binary form must reproduce the above > + * copyright notice, this list of conditions and the > + * following disclaimer in the documentation and/or other > + * materials provided with the distribution. > + * > + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND > + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, > + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF > + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE > + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR > + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, > + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, > + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR > + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS > + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, > + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING > + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE > + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF > + * SUCH DAMAGE. > + */ > + > +#ifndef _XEN_WARNINGS_H > +#define _XEN_WARNINGS_H > + > +#include <ntddk.h> > + > +// Disable warnings necessary to include xen headers > + > +# pragma warning(disable:4214) // nonstandard extension used : bit field > types other than int > +# pragma warning(disable:4200) // nonstandard extension used : zero-sized > array in struct/union > + > +#endif // _XEN_WARNINGS_H > diff --git a/include/xen.h b/include/xen.h > new file mode 100755 > index 0000000..27faf26 > --- /dev/null > +++ b/include/xen.h > @@ -0,0 +1,45 @@ > +/* Copyright (c) Citrix Systems Inc. > + * All rights reserved. > + * > + * Redistribution and use in source and binary forms, > + * with or without modification, are permitted provided > + * that the following conditions are met: > + * > + * * Redistributions of source code must retain the above > + * copyright notice, this list of conditions and the > + * following disclaimer. > + * * Redistributions in binary form must reproduce the above > + * copyright notice, this list of conditions and the > + * following disclaimer in the documentation and/or other > + * materials provided with the distribution. > + * > + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND > + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, > + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF > + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE > + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR > + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, > + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, > + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR > + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS > + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, > + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING > + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE > + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF > + * SUCH DAMAGE. > + */ > + > +#ifndef _XEN_H > +#define _XEN_H > + > +#include <ntddk.h> > + > +#include <xen-version.h> > +#include <xen-types.h> > +#include <xen-warnings.h> > + > +#include <public/io/ring.h> > +#include <public/io/console.h> > +#include <public/io/xenbus.h> > + > +#endif // _XEN_H > diff --git a/include/xen/public/arch-x86/xen-x86_32.h > b/include/xen/public/arch-x86/xen-x86_32.h > new file mode 100755 > index 0000000..d23340b > --- /dev/null > +++ b/include/xen/public/arch-x86/xen-x86_32.h > @@ -0,0 +1,169 @@ > +/********************************************************* > ********************* > + * 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 > xen_mk_ulong(__HYPERVISOR_VIRT_START_PAE) > +#define MACH2PHYS_VIRT_START_PAE > xen_mk_ulong(__MACH2PHYS_VIRT_START_PAE) > +#define MACH2PHYS_VIRT_END_PAE > xen_mk_ulong(__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 \ > + xen_mk_ulong(__HYPERVISOR_VIRT_START_NONPAE) > +#define MACH2PHYS_VIRT_START_NONPAE \ > + xen_mk_ulong(__MACH2PHYS_VIRT_START_NONPAE) > +#define MACH2PHYS_VIRT_END_NONPAE \ > + xen_mk_ulong(__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 > xen_mk_ulong(__HYPERVISOR_VIRT_START) > +#endif > + > +#define MACH2PHYS_VIRT_START > xen_mk_ulong(__MACH2PHYS_VIRT_START) > +#define MACH2PHYS_VIRT_END > xen_mk_ulong(__MACH2PHYS_VIRT_END) > +#define MACH2PHYS_NR_ENTRIES ((MACH2PHYS_VIRT_END- > MACH2PHYS_VIRT_START)>>2) > +#ifndef machine_to_phys_mapping > +#define machine_to_phys_mapping ((ULONG_PTR > *)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 int64_aligned_t int64_t __attribute__((aligned(8))) > +#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 { > + ULONG_PTR cr2; > + ULONG_PTR pad[5]; /* sizeof(vcpu_info_t) == 64 */ > +}; > +typedef struct arch_vcpu_info arch_vcpu_info_t; > + > +struct xen_callback { > + ULONG_PTR cs; > + ULONG_PTR 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: > + */ > diff --git a/include/xen/public/arch-x86/xen-x86_64.h > b/include/xen/public/arch-x86/xen-x86_64.h > new file mode 100755 > index 0000000..2f53f69 > --- /dev/null > +++ b/include/xen/public/arch-x86/xen-x86_64.h > @@ -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 > xen_mk_ulong(__HYPERVISOR_VIRT_START) > +#define HYPERVISOR_VIRT_END > xen_mk_ulong(__HYPERVISOR_VIRT_END) > +#endif > + > +#define MACH2PHYS_VIRT_START > xen_mk_ulong(__MACH2PHYS_VIRT_START) > +#define MACH2PHYS_VIRT_END > xen_mk_ulong(__MACH2PHYS_VIRT_END) > +#define MACH2PHYS_NR_ENTRIES ((MACH2PHYS_VIRT_END- > MACH2PHYS_VIRT_START)>>3) > +#ifndef machine_to_phys_mapping > +#define machine_to_phys_mapping ((ULONG_PTR > *)HYPERVISOR_VIRT_START) > +#endif > + > +/* > + * int HYPERVISOR_set_segment_base(unsigned int which, ULONG_PTR > 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) ((ULONG_PTR)(pfn) << 12) > +#define xen_cr3_to_pfn(cr3) ((ULONG_PTR)(cr3) >> 12) > + > +struct arch_vcpu_info { > + ULONG_PTR cr2; > + ULONG_PTR pad; /* sizeof(vcpu_info_t) == 64 */ > +}; > +typedef struct arch_vcpu_info arch_vcpu_info_t; > + > +typedef ULONG_PTR 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: > + */ > diff --git a/include/xen/public/arch-x86/xen.h b/include/xen/public/arch- > x86/xen.h > new file mode 100755 > index 0000000..05db77f > --- /dev/null > +++ b/include/xen/public/arch-x86/xen.h > @@ -0,0 +1,338 @@ > +/********************************************************* > ********************* > + * 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) > +#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 ULONG_PTR 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 ULONG_PTR xen_ulong_t; > +#define PRI_xen_ulong "lx" > + > +/* > + * ` enum neg_errnoval > + * ` HYPERVISOR_stack_switch(ULONG_PTR ss, ULONG_PTR 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 > */ > + ULONG_PTR 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) > + ULONG_PTR flags; /* VGCF_* flags */ > + struct cpu_user_regs user_regs; /* User-level CPU registers > */ > + struct trap_info trap_ctxt[256]; /* Virtual IDT > */ > + ULONG_PTR ldt_base, ldt_ents; /* LDT (linear address, # ents) */ > + ULONG_PTR gdt_frames[16], gdt_ents; /* GDT (machine frames, # ents) > */ > + ULONG_PTR kernel_ss, kernel_sp; /* Virtual TSS (only SS1/SP1) */ > + /* NB. User pagetable on x86/64 is placed in ctrlreg[1]. */ > + ULONG_PTR ctrlreg[8]; /* CR0-CR7 (control registers) */ > + ULONG_PTR debugreg[8]; /* DB0-DB7 (debug registers) */ > +#ifdef __i386__ > + ULONG_PTR event_callback_cs; /* CS:EIP of event callback */ > + ULONG_PTR event_callback_eip; > + ULONG_PTR failsafe_callback_cs; /* CS:EIP of failsafe callback */ > + ULONG_PTR failsafe_callback_eip; > +#else > + ULONG_PTR event_callback_eip; > + ULONG_PTR failsafe_callback_eip; > +#ifdef __XEN__ > + union { > + ULONG_PTR 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 > + ULONG_PTR syscall_callback_eip; > +#endif > +#endif > + ULONG_PTR 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 { > + /* > + * Number of valid entries in the p2m table(s) anchored at > + * pfn_to_mfn_frame_list_list and/or p2m_vaddr. > + */ > + ULONG_PTR max_pfn; > + /* > + * Frame containing list of mfns containing list of mfns containing p2m. > + * A value of 0 indicates it has not yet been set up, ~0 indicates it has > + * been set to invalid e.g. due to the p2m being too large for the > 3-level > + * p2m tree. In this case the linear mapper p2m list anchored at > p2m_vaddr > + * is to be used. > + */ > + xen_pfn_t pfn_to_mfn_frame_list_list; > + ULONG_PTR nmi_reason; > + /* > + * Following three fields are valid if p2m_cr3 contains a value different > + * from 0. > + * p2m_cr3 is the root of the address space where p2m_vaddr is valid. > + * p2m_cr3 is in the same format as a cr3 value in the vcpu register > state > + * and holds the folded machine frame number (via xen_pfn_to_cr3) of a > + * L3 or L4 page table. > + * p2m_vaddr holds the virtual address of the linear p2m list. All > entries > + * in the range [0...max_pfn[ are accessible via this pointer. > + * p2m_generation will be incremented by the guest before and after > each > + * change of the mappings of the p2m list. p2m_generation starts at 0 and > + * a value with the least significant bit set indicates that a mapping > + * update is in progress. This allows guest external software (e.g. in > Dom0) > + * to verify that read mappings are consistent and whether they have > changed > + * since the last check. > + * Modifying a p2m element in the linear p2m list is allowed via an > atomic > + * write only. > + */ > + ULONG_PTR p2m_cr3; /* cr3 value of the p2m address space */ > + ULONG_PTR p2m_vaddr; /* virtual address of the p2m list */ > + ULONG_PTR p2m_generation; /* generation count of p2m mapping */ > +#ifdef __i386__ > + /* There's no room for this field in the generic structure. */ > + uint32_t wc_sec_hi; > +#endif > +}; > +typedef struct arch_shared_info arch_shared_info_t; > + > +#if defined(__XEN__) || defined(__XEN_TOOLS__) > +/* > + * struct xen_arch_domainconfig's ABI is covered by > + * XEN_DOMCTL_INTERFACE_VERSION. > + */ > +struct xen_arch_domainconfig { > +#define _XEN_X86_EMU_LAPIC 0 > +#define XEN_X86_EMU_LAPIC (1U<<_XEN_X86_EMU_LAPIC) > +#define _XEN_X86_EMU_HPET 1 > +#define XEN_X86_EMU_HPET (1U<<_XEN_X86_EMU_HPET) > +#define _XEN_X86_EMU_PM 2 > +#define XEN_X86_EMU_PM (1U<<_XEN_X86_EMU_PM) > +#define _XEN_X86_EMU_RTC 3 > +#define XEN_X86_EMU_RTC (1U<<_XEN_X86_EMU_RTC) > +#define _XEN_X86_EMU_IOAPIC 4 > +#define XEN_X86_EMU_IOAPIC (1U<<_XEN_X86_EMU_IOAPIC) > +#define _XEN_X86_EMU_PIC 5 > +#define XEN_X86_EMU_PIC (1U<<_XEN_X86_EMU_PIC) > +#define _XEN_X86_EMU_VGA 6 > +#define XEN_X86_EMU_VGA (1U<<_XEN_X86_EMU_VGA) > +#define _XEN_X86_EMU_IOMMU 7 > +#define XEN_X86_EMU_IOMMU (1U<<_XEN_X86_EMU_IOMMU) > +#define _XEN_X86_EMU_PIT 8 > +#define XEN_X86_EMU_PIT (1U<<_XEN_X86_EMU_PIT) > + > +#define XEN_X86_EMU_ALL (XEN_X86_EMU_LAPIC | > XEN_X86_EMU_HPET | \ > + XEN_X86_EMU_PM | XEN_X86_EMU_RTC | > \ > + XEN_X86_EMU_IOAPIC | XEN_X86_EMU_PIC | > \ > + XEN_X86_EMU_VGA | XEN_X86_EMU_IOMMU | > \ > + XEN_X86_EMU_PIT) > + uint32_t emulation_flags; > +}; > +#endif > + > +#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, ULONG_PTR value); > + * > + * ` ULONG_PTR > + * ` HYPERVISOR_get_debugreg(int regno); > + * For 0<=reg<=7, returns the debug register value. > + * For other values of reg, returns ((ULONG_PTR)-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: > + */ > diff --git a/include/xen/public/errno.h b/include/xen/public/errno.h > new file mode 100755 > index 0000000..e440237 > --- /dev/null > +++ b/include/xen/public/errno.h > @@ -0,0 +1,124 @@ > +/* > + * There are two expected ways of including this header. > + * > + * 1) The "default" case (expected from tools etc). > + * > + * Simply #include <public/errno.h> > + * > + * In this circumstance, normal header guards apply and the includer shall > get > + * an enumeration in the XEN_xxx namespace, appropriate for C or > assembly. > + * > + * 2) The special case where the includer provides a XEN_ERRNO() in scope. > + * > + * In this case, no inclusion guards apply and the caller is responsible for > + * their XEN_ERRNO() being appropriate in the included context. The > header > + * will unilaterally #undef XEN_ERRNO(). > + */ > + > +#ifndef XEN_ERRNO > + > +/* > + * Includer has not provided a custom XEN_ERRNO(). Arrange for normal > header > + * guards, an automatic enum (for C code) and constants in the XEN_xxx > + * namespace. > + */ > +#ifndef __XEN_PUBLIC_ERRNO_H__ > +#define __XEN_PUBLIC_ERRNO_H__ > + > +#define XEN_ERRNO_DEFAULT_INCLUDE > + > +#ifndef __ASSEMBLY__ > + > +#define XEN_ERRNO(name, value) XEN_##name = value, > +enum xen_errno { > + > +#elif __XEN_INTERFACE_VERSION__ < 0x00040700 > + > +#define XEN_ERRNO(name, value) .equ XEN_##name, value > + > +#endif /* __ASSEMBLY__ */ > + > +#endif /* __XEN_PUBLIC_ERRNO_H__ */ > +#endif /* !XEN_ERRNO */ > + > +/* ` enum neg_errnoval { [ -Efoo for each Efoo in the list below ] } */ > +/* ` enum errnoval { */ > + > +#ifdef XEN_ERRNO > + > +/* > + * Values originating from x86 Linux. Please consider using respective > + * values when adding new definitions here. > + * > + * The set of identifiers to be added here shouldn't extend beyond what > + * POSIX mandates (see e.g. > + * > http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/errno.h.html) > + * with the exception that we support some optional (XSR) values > + * specified there (but no new ones should be added). > + */ > + > +XEN_ERRNO(EPERM, 1) /* Operation not permitted */ > +XEN_ERRNO(ENOENT, 2) /* No such file or directory */ > +XEN_ERRNO(ESRCH, 3) /* No such process */ > +#ifdef __XEN__ /* Internal only, should never be exposed to the guest. */ > +XEN_ERRNO(EINTR, 4) /* Interrupted system call */ > +#endif > +XEN_ERRNO(EIO, 5) /* I/O error */ > +XEN_ERRNO(ENXIO, 6) /* No such device or address */ > +XEN_ERRNO(E2BIG, 7) /* Arg list too LONG_PTR */ > +XEN_ERRNO(ENOEXEC, 8) /* Exec format error */ > +XEN_ERRNO(EBADF, 9) /* Bad file number */ > +XEN_ERRNO(ECHILD, 10) /* No child processes */ > +XEN_ERRNO(EAGAIN, 11) /* Try again */ > +XEN_ERRNO(EWOULDBLOCK, 11) /* Operation would block. Aliases > EAGAIN */ > +XEN_ERRNO(ENOMEM, 12) /* Out of memory */ > +XEN_ERRNO(EACCES, 13) /* Permission denied */ > +XEN_ERRNO(EFAULT, 14) /* Bad address */ > +XEN_ERRNO(EBUSY, 16) /* Device or resource busy */ > +XEN_ERRNO(EEXIST, 17) /* File exists */ > +XEN_ERRNO(EXDEV, 18) /* Cross-device link */ > +XEN_ERRNO(ENODEV, 19) /* No such device */ > +XEN_ERRNO(EISDIR, 21) /* Is a directory */ > +XEN_ERRNO(EINVAL, 22) /* Invalid argument */ > +XEN_ERRNO(ENFILE, 23) /* File table overflow */ > +XEN_ERRNO(EMFILE, 24) /* Too many open files */ > +XEN_ERRNO(ENOSPC, 28) /* No space left on device */ > +XEN_ERRNO(EROFS, 30) /* Read-only file system */ > +XEN_ERRNO(EMLINK, 31) /* Too many links */ > +XEN_ERRNO(EDOM, 33) /* Math argument out of domain of > func */ > +XEN_ERRNO(ERANGE, 34) /* Math result not representable */ > +XEN_ERRNO(EDEADLK, 35) /* Resource deadlock would occur */ > +XEN_ERRNO(EDEADLOCK, 35) /* Resource deadlock would occur. > Aliases EDEADLK */ > +XEN_ERRNO(ENAMETOOLONG, 36) /* File name too LONG_PTR > */ > +XEN_ERRNO(ENOLCK, 37) /* No record locks available */ > +XEN_ERRNO(ENOTEMPTY, 39) /* Directory not empty */ > +XEN_ERRNO(ENOSYS, 38) /* Function not implemented */ > +XEN_ERRNO(ENODATA, 61) /* No data available */ > +XEN_ERRNO(ETIME, 62) /* Timer expired */ > +XEN_ERRNO(EBADMSG, 74) /* Not a data message */ > +XEN_ERRNO(EOVERFLOW, 75) /* Value too large for defined data > type */ > +XEN_ERRNO(EILSEQ, 84) /* Illegal byte sequence */ > +#ifdef __XEN__ /* Internal only, should never be exposed to the guest. */ > +XEN_ERRNO(ERESTART, 85) /* Interrupted system call should be > restarted */ > +#endif > +XEN_ERRNO(ENOTSOCK, 88) /* Socket operation on non-socket */ > +XEN_ERRNO(EOPNOTSUPP, 95) /* Operation not supported on > transport endpoint */ > +XEN_ERRNO(EADDRINUSE, 98) /* Address already in use */ > +XEN_ERRNO(EADDRNOTAVAIL, 99) /* Cannot assign requested address > */ > +XEN_ERRNO(ENOBUFS, 105) /* No buffer space available */ > +XEN_ERRNO(EISCONN, 106) /* Transport endpoint is already > connected */ > +XEN_ERRNO(ENOTCONN, 107) /* Transport endpoint is not > connected */ > +XEN_ERRNO(ETIMEDOUT, 110) /* Connection timed out */ > + > +#undef XEN_ERRNO > +#endif /* XEN_ERRNO */ > +/* ` } */ > + > +/* Clean up from a default include. Close the enum (for C). */ > +#ifdef XEN_ERRNO_DEFAULT_INCLUDE > +#undef XEN_ERRNO_DEFAULT_INCLUDE > +#ifndef __ASSEMBLY__ > +}; > +#endif > + > +#endif /* XEN_ERRNO_DEFAULT_INCLUDE */ > diff --git a/include/xen/public/grant_table.h > b/include/xen/public/grant_table.h > new file mode 100755 > index 0000000..b68ffdd > --- /dev/null > +++ b/include/xen/public/grant_table.h > @@ -0,0 +1,684 @@ > +/********************************************************* > ********************* > + * 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: GFN that @domid is allowed to map and access. > [GST] > + * GTF_accept_transfer: GFN that @domid is allowed to transfer into. > [GST] > + * GTF_transfer_completed: MFN whose ownership transferred by > @domid > + * (non-translated guests only). [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 > +#define GNTTABOP_cache_flush 12 > +#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, > <status> > + * 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 LONG_PTRer > 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 gnttab_copy_ptr { > + 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); > + > +/* > + * Issue one or more cache maintenance operations on a portion of a > + * page granted to the calling domain by a foreign domain. > + */ > +struct gnttab_cache_flush { > + union { > + uint64_t dev_bus_addr; > + grant_ref_t ref; > + } a; > + uint16_t offset; /* offset from start of grant */ > + uint16_t length; /* size within the grant */ > +#define GNTTAB_CACHE_CLEAN (1<<0) > +#define GNTTAB_CACHE_INVAL (1<<1) > +#define GNTTAB_CACHE_SOURCE_GREF (1<<31) > + uint32_t op; > +}; > +typedef struct gnttab_cache_flush gnttab_cache_flush_t; > +DEFINE_XEN_GUEST_HANDLE(gnttab_cache_flush_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: > + */ > diff --git a/include/xen/public/io/console.h > b/include/xen/public/io/console.h > new file mode 100755 > index 0000000..6496018 > --- /dev/null > +++ b/include/xen/public/io/console.h > @@ -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: > + */ > diff --git a/include/xen/public/io/ring.h b/include/xen/public/io/ring.h > new file mode 100755 > index 0000000..1d29cc0 > --- /dev/null > +++ b/include/xen/public/io/ring.h > @@ -0,0 +1,326 @@ > +/********************************************************* > ********************* > + * 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_PTR)(_s)->ring + (LONG_PTR)(_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]; \ > + } pvt; \ > + 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)->pvt.pvt_pad, 0, sizeof((_s)->pvt.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)) > + > +/* > + * Get a local copy of a request. > + * > + * Use this in preference to RING_GET_REQUEST() so all processing is > + * done on a local copy that cannot be modified by the other end. > + * > + * Note that https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58145 may > cause this > + * to be ineffective where _req is a struct which consists of only bitfields. > + */ > +#define RING_COPY_REQUEST(_r, _idx, _req) do { > \ > + /* Use volatile to force the copy into _req. */ \ > + *(_req) = *(volatile typeof(_req))RING_GET_REQUEST(_r, _idx); > \ > +} while (0) > + > +#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: > + */ > diff --git a/include/xen/public/io/xenbus.h > b/include/xen/public/io/xenbus.h > new file mode 100755 > index 0000000..927f9db > --- /dev/null > +++ b/include/xen/public/io/xenbus.h > @@ -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: > + */ > diff --git a/include/xen/public/trace.h b/include/xen/public/trace.h > new file mode 100755 > index 0000000..95b00e8 > --- /dev/null > +++ b/include/xen/public/trace.h > @@ -0,0 +1,337 @@ > +/********************************************************* > ********************* > + * include/public/trace.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. > + * > + * Mark Williamson, (C) 2004 Intel Research Cambridge > + * Copyright (C) 2005 Bin Ren > + */ > + > +#ifndef __XEN_PUBLIC_TRACE_H__ > +#define __XEN_PUBLIC_TRACE_H__ > + > +#define TRACE_EXTRA_MAX 7 > +#define TRACE_EXTRA_SHIFT 28 > + > +/* Trace classes */ > +#define TRC_CLS_SHIFT 16 > +#define TRC_GEN 0x0001f000 /* General trace */ > +#define TRC_SCHED 0x0002f000 /* Xen Scheduler trace */ > +#define TRC_DOM0OP 0x0004f000 /* Xen DOM0 operation trace */ > +#define TRC_HVM 0x0008f000 /* Xen HVM trace */ > +#define TRC_MEM 0x0010f000 /* Xen memory trace */ > +#define TRC_PV 0x0020f000 /* Xen PV traces */ > +#define TRC_SHADOW 0x0040f000 /* Xen shadow tracing */ > +#define TRC_HW 0x0080f000 /* Xen hardware-related traces */ > +#define TRC_GUEST 0x0800f000 /* Guest-generated traces */ > +#define TRC_ALL 0x0ffff000 > +#define TRC_HD_TO_EVENT(x) ((x)&0x0fffffff) > +#define TRC_HD_CYCLE_FLAG (1UL<<31) > +#define TRC_HD_INCLUDES_CYCLE_COUNT(x) ( !!( (x) & > TRC_HD_CYCLE_FLAG ) ) > +#define TRC_HD_EXTRA(x) > (((x)>>TRACE_EXTRA_SHIFT)&TRACE_EXTRA_MAX) > + > +/* Trace subclasses */ > +#define TRC_SUBCLS_SHIFT 12 > + > +/* trace subclasses for SVM */ > +#define TRC_HVM_ENTRYEXIT 0x00081000 /* VMENTRY and #VMEXIT > */ > +#define TRC_HVM_HANDLER 0x00082000 /* various HVM handlers */ > +#define TRC_HVM_EMUL 0x00084000 /* emulated devices */ > + > +#define TRC_SCHED_MIN 0x00021000 /* Just runstate changes */ > +#define TRC_SCHED_CLASS 0x00022000 /* Scheduler-specific */ > +#define TRC_SCHED_VERBOSE 0x00028000 /* More inclusive scheduling > */ > + > +/* > + * The highest 3 bits of the last 12 bits of TRC_SCHED_CLASS above are > + * reserved for encoding what scheduler produced the information. The > + * actual event is encoded in the last 9 bits. > + * > + * This means we have 8 scheduling IDs available (which means at most 8 > + * schedulers generating events) and, in each scheduler, up to 512 > + * different events. > + */ > +#define TRC_SCHED_ID_BITS 3 > +#define TRC_SCHED_ID_SHIFT (TRC_SUBCLS_SHIFT - TRC_SCHED_ID_BITS) > +#define TRC_SCHED_ID_MASK (((1UL<<TRC_SCHED_ID_BITS) - 1) << > TRC_SCHED_ID_SHIFT) > +#define TRC_SCHED_EVT_MASK (~(TRC_SCHED_ID_MASK)) > + > +/* Per-scheduler IDs, to identify scheduler specific events */ > +#define TRC_SCHED_CSCHED 0 > +#define TRC_SCHED_CSCHED2 1 > +/* #define XEN_SCHEDULER_SEDF 2 (Removed) */ > +#define TRC_SCHED_ARINC653 3 > +#define TRC_SCHED_RTDS 4 > + > +/* Per-scheduler tracing */ > +#define TRC_SCHED_CLASS_EVT(_c, _e) \ > + ( ( TRC_SCHED_CLASS | \ > + ((TRC_SCHED_##_c << TRC_SCHED_ID_SHIFT) & TRC_SCHED_ID_MASK) > ) + \ > + (_e & TRC_SCHED_EVT_MASK) ) > + > +/* Trace classes for DOM0 operations */ > +#define TRC_DOM0_DOMOPS 0x00041000 /* Domains manipulations */ > + > +/* Trace classes for Hardware */ > +#define TRC_HW_PM 0x00801000 /* Power management traces */ > +#define TRC_HW_IRQ 0x00802000 /* Traces relating to the handling > of > IRQs */ > + > +/* Trace events per class */ > +#define TRC_LOST_RECORDS (TRC_GEN + 1) > +#define TRC_TRACE_WRAP_BUFFER (TRC_GEN + 2) > +#define TRC_TRACE_CPU_CHANGE (TRC_GEN + 3) > + > +#define TRC_SCHED_RUNSTATE_CHANGE (TRC_SCHED_MIN + 1) > +#define TRC_SCHED_CONTINUE_RUNNING (TRC_SCHED_MIN + 2) > +#define TRC_SCHED_DOM_ADD (TRC_SCHED_VERBOSE + 1) > +#define TRC_SCHED_DOM_REM (TRC_SCHED_VERBOSE + 2) > +#define TRC_SCHED_SLEEP (TRC_SCHED_VERBOSE + 3) > +#define TRC_SCHED_WAKE (TRC_SCHED_VERBOSE + 4) > +#define TRC_SCHED_YIELD (TRC_SCHED_VERBOSE + 5) > +#define TRC_SCHED_BLOCK (TRC_SCHED_VERBOSE + 6) > +#define TRC_SCHED_SHUTDOWN (TRC_SCHED_VERBOSE + 7) > +#define TRC_SCHED_CTL (TRC_SCHED_VERBOSE + 8) > +#define TRC_SCHED_ADJDOM (TRC_SCHED_VERBOSE + 9) > +#define TRC_SCHED_SWITCH (TRC_SCHED_VERBOSE + 10) > +#define TRC_SCHED_S_TIMER_FN (TRC_SCHED_VERBOSE + 11) > +#define TRC_SCHED_T_TIMER_FN (TRC_SCHED_VERBOSE + 12) > +#define TRC_SCHED_DOM_TIMER_FN (TRC_SCHED_VERBOSE + 13) > +#define TRC_SCHED_SWITCH_INFPREV (TRC_SCHED_VERBOSE + 14) > +#define TRC_SCHED_SWITCH_INFNEXT (TRC_SCHED_VERBOSE + 15) > +#define TRC_SCHED_SHUTDOWN_CODE (TRC_SCHED_VERBOSE + 16) > + > +#define TRC_DOM0_DOM_ADD (TRC_DOM0_DOMOPS + 1) > +#define TRC_DOM0_DOM_REM (TRC_DOM0_DOMOPS + 2) > + > +#define TRC_MEM_PAGE_GRANT_MAP (TRC_MEM + 1) > +#define TRC_MEM_PAGE_GRANT_UNMAP (TRC_MEM + 2) > +#define TRC_MEM_PAGE_GRANT_TRANSFER (TRC_MEM + 3) > +#define TRC_MEM_SET_P2M_ENTRY (TRC_MEM + 4) > +#define TRC_MEM_DECREASE_RESERVATION (TRC_MEM + 5) > +#define TRC_MEM_POD_POPULATE (TRC_MEM + 16) > +#define TRC_MEM_POD_ZERO_RECLAIM (TRC_MEM + 17) > +#define TRC_MEM_POD_SUPERPAGE_SPLINTER (TRC_MEM + 18) > + > +#define TRC_PV_ENTRY 0x00201000 /* Hypervisor entry points for PV > guests. */ > +#define TRC_PV_SUBCALL 0x00202000 /* Sub-call in a multicall hypercall */ > + > +#define TRC_PV_HYPERCALL (TRC_PV_ENTRY + 1) > +#define TRC_PV_TRAP (TRC_PV_ENTRY + 3) > +#define TRC_PV_PAGE_FAULT (TRC_PV_ENTRY + 4) > +#define TRC_PV_FORCED_INVALID_OP (TRC_PV_ENTRY + 5) > +#define TRC_PV_EMULATE_PRIVOP (TRC_PV_ENTRY + 6) > +#define TRC_PV_EMULATE_4GB (TRC_PV_ENTRY + 7) > +#define TRC_PV_MATH_STATE_RESTORE (TRC_PV_ENTRY + 8) > +#define TRC_PV_PAGING_FIXUP (TRC_PV_ENTRY + 9) > +#define TRC_PV_GDT_LDT_MAPPING_FAULT (TRC_PV_ENTRY + 10) > +#define TRC_PV_PTWR_EMULATION (TRC_PV_ENTRY + 11) > +#define TRC_PV_PTWR_EMULATION_PAE (TRC_PV_ENTRY + 12) > +#define TRC_PV_HYPERCALL_V2 (TRC_PV_ENTRY + 13) > +#define TRC_PV_HYPERCALL_SUBCALL (TRC_PV_SUBCALL + 14) > + > +/* > + * TRC_PV_HYPERCALL_V2 format > + * > + * Only some of the hypercall argument are recorded. Bit fields A0 to > + * A5 in the first extra word are set if the argument is present and > + * the arguments themselves are packed sequentially in the following > + * words. > + * > + * The TRC_64_FLAG bit is not set for these events (even if there are > + * 64-bit arguments in the record). > + * > + * Word > + * 0 bit 31 30|29 28|27 26|25 24|23 22|21 20|19 ... 0 > + * A5 |A4 |A3 |A2 |A1 |A0 |Hypercall op > + * 1 First 32 bit (or low word of first 64 bit) arg in record > + * 2 Second 32 bit (or high word of first 64 bit) arg in record > + * ... > + * > + * A0-A5 bitfield values: > + * > + * 00b Argument not present > + * 01b 32-bit argument present > + * 10b 64-bit argument present > + * 11b Reserved > + */ > +#define TRC_PV_HYPERCALL_V2_ARG_32(i) (0x1 << (20 + 2*(i))) > +#define TRC_PV_HYPERCALL_V2_ARG_64(i) (0x2 << (20 + 2*(i))) > +#define TRC_PV_HYPERCALL_V2_ARG_MASK (0xfff00000) > + > +#define TRC_SHADOW_NOT_SHADOW (TRC_SHADOW + 1) > +#define TRC_SHADOW_FAST_PROPAGATE (TRC_SHADOW + 2) > +#define TRC_SHADOW_FAST_MMIO (TRC_SHADOW + 3) > +#define TRC_SHADOW_FALSE_FAST_PATH (TRC_SHADOW + 4) > +#define TRC_SHADOW_MMIO (TRC_SHADOW + 5) > +#define TRC_SHADOW_FIXUP (TRC_SHADOW + 6) > +#define TRC_SHADOW_DOMF_DYING (TRC_SHADOW + 7) > +#define TRC_SHADOW_EMULATE (TRC_SHADOW + 8) > +#define TRC_SHADOW_EMULATE_UNSHADOW_USER (TRC_SHADOW + > 9) > +#define TRC_SHADOW_EMULATE_UNSHADOW_EVTINJ (TRC_SHADOW + > 10) > +#define TRC_SHADOW_EMULATE_UNSHADOW_UNHANDLED > (TRC_SHADOW + 11) > +#define TRC_SHADOW_WRMAP_BF (TRC_SHADOW + 12) > +#define TRC_SHADOW_PREALLOC_UNPIN (TRC_SHADOW + 13) > +#define TRC_SHADOW_RESYNC_FULL (TRC_SHADOW + 14) > +#define TRC_SHADOW_RESYNC_ONLY (TRC_SHADOW + 15) > + > +/* trace events per subclass */ > +#define TRC_HVM_NESTEDFLAG (0x400) > +#define TRC_HVM_VMENTRY (TRC_HVM_ENTRYEXIT + 0x01) > +#define TRC_HVM_VMEXIT (TRC_HVM_ENTRYEXIT + 0x02) > +#define TRC_HVM_VMEXIT64 (TRC_HVM_ENTRYEXIT + TRC_64_FLAG + > 0x02) > +#define TRC_HVM_PF_XEN (TRC_HVM_HANDLER + 0x01) > +#define TRC_HVM_PF_XEN64 (TRC_HVM_HANDLER + TRC_64_FLAG + > 0x01) > +#define TRC_HVM_PF_INJECT (TRC_HVM_HANDLER + 0x02) > +#define TRC_HVM_PF_INJECT64 (TRC_HVM_HANDLER + TRC_64_FLAG + > 0x02) > +#define TRC_HVM_INJ_EXC (TRC_HVM_HANDLER + 0x03) > +#define TRC_HVM_INJ_VIRQ (TRC_HVM_HANDLER + 0x04) > +#define TRC_HVM_REINJ_VIRQ (TRC_HVM_HANDLER + 0x05) > +#define TRC_HVM_IO_READ (TRC_HVM_HANDLER + 0x06) > +#define TRC_HVM_IO_WRITE (TRC_HVM_HANDLER + 0x07) > +#define TRC_HVM_CR_READ (TRC_HVM_HANDLER + 0x08) > +#define TRC_HVM_CR_READ64 (TRC_HVM_HANDLER + TRC_64_FLAG + > 0x08) > +#define TRC_HVM_CR_WRITE (TRC_HVM_HANDLER + 0x09) > +#define TRC_HVM_CR_WRITE64 (TRC_HVM_HANDLER + TRC_64_FLAG + > 0x09) > +#define TRC_HVM_DR_READ (TRC_HVM_HANDLER + 0x0A) > +#define TRC_HVM_DR_WRITE (TRC_HVM_HANDLER + 0x0B) > +#define TRC_HVM_MSR_READ (TRC_HVM_HANDLER + 0x0C) > +#define TRC_HVM_MSR_WRITE (TRC_HVM_HANDLER + 0x0D) > +#define TRC_HVM_CPUID (TRC_HVM_HANDLER + 0x0E) > +#define TRC_HVM_INTR (TRC_HVM_HANDLER + 0x0F) > +#define TRC_HVM_NMI (TRC_HVM_HANDLER + 0x10) > +#define TRC_HVM_SMI (TRC_HVM_HANDLER + 0x11) > +#define TRC_HVM_VMMCALL (TRC_HVM_HANDLER + 0x12) > +#define TRC_HVM_HLT (TRC_HVM_HANDLER + 0x13) > +#define TRC_HVM_INVLPG (TRC_HVM_HANDLER + 0x14) > +#define TRC_HVM_INVLPG64 (TRC_HVM_HANDLER + TRC_64_FLAG + > 0x14) > +#define TRC_HVM_MCE (TRC_HVM_HANDLER + 0x15) > +#define TRC_HVM_IOPORT_READ (TRC_HVM_HANDLER + 0x16) > +#define TRC_HVM_IOMEM_READ (TRC_HVM_HANDLER + 0x17) > +#define TRC_HVM_CLTS (TRC_HVM_HANDLER + 0x18) > +#define TRC_HVM_LMSW (TRC_HVM_HANDLER + 0x19) > +#define TRC_HVM_LMSW64 (TRC_HVM_HANDLER + TRC_64_FLAG + > 0x19) > +#define TRC_HVM_RDTSC (TRC_HVM_HANDLER + 0x1a) > +#define TRC_HVM_INTR_WINDOW (TRC_HVM_HANDLER + 0x20) > +#define TRC_HVM_NPF (TRC_HVM_HANDLER + 0x21) > +#define TRC_HVM_REALMODE_EMULATE (TRC_HVM_HANDLER + 0x22) > +#define TRC_HVM_TRAP (TRC_HVM_HANDLER + 0x23) > +#define TRC_HVM_TRAP_DEBUG (TRC_HVM_HANDLER + 0x24) > +#define TRC_HVM_VLAPIC (TRC_HVM_HANDLER + 0x25) > + > +#define TRC_HVM_IOPORT_WRITE (TRC_HVM_HANDLER + 0x216) > +#define TRC_HVM_IOMEM_WRITE (TRC_HVM_HANDLER + 0x217) > + > +/* Trace events for emulated devices */ > +#define TRC_HVM_EMUL_HPET_START_TIMER (TRC_HVM_EMUL + 0x1) > +#define TRC_HVM_EMUL_PIT_START_TIMER (TRC_HVM_EMUL + 0x2) > +#define TRC_HVM_EMUL_RTC_START_TIMER (TRC_HVM_EMUL + 0x3) > +#define TRC_HVM_EMUL_LAPIC_START_TIMER (TRC_HVM_EMUL + 0x4) > +#define TRC_HVM_EMUL_HPET_STOP_TIMER (TRC_HVM_EMUL + 0x5) > +#define TRC_HVM_EMUL_PIT_STOP_TIMER (TRC_HVM_EMUL + 0x6) > +#define TRC_HVM_EMUL_RTC_STOP_TIMER (TRC_HVM_EMUL + 0x7) > +#define TRC_HVM_EMUL_LAPIC_STOP_TIMER (TRC_HVM_EMUL + 0x8) > +#define TRC_HVM_EMUL_PIT_TIMER_CB (TRC_HVM_EMUL + 0x9) > +#define TRC_HVM_EMUL_LAPIC_TIMER_CB (TRC_HVM_EMUL + 0xA) > +#define TRC_HVM_EMUL_PIC_INT_OUTPUT (TRC_HVM_EMUL + 0xB) > +#define TRC_HVM_EMUL_PIC_KICK (TRC_HVM_EMUL + 0xC) > +#define TRC_HVM_EMUL_PIC_INTACK (TRC_HVM_EMUL + 0xD) > +#define TRC_HVM_EMUL_PIC_POSEDGE (TRC_HVM_EMUL + 0xE) > +#define TRC_HVM_EMUL_PIC_NEGEDGE (TRC_HVM_EMUL + 0xF) > +#define TRC_HVM_EMUL_PIC_PEND_IRQ_CALL (TRC_HVM_EMUL + 0x10) > +#define TRC_HVM_EMUL_LAPIC_PIC_INTR (TRC_HVM_EMUL + 0x11) > + > +/* trace events for per class */ > +#define TRC_PM_FREQ_CHANGE (TRC_HW_PM + 0x01) > +#define TRC_PM_IDLE_ENTRY (TRC_HW_PM + 0x02) > +#define TRC_PM_IDLE_EXIT (TRC_HW_PM + 0x03) > + > +/* Trace events for IRQs */ > +#define TRC_HW_IRQ_MOVE_CLEANUP_DELAY (TRC_HW_IRQ + 0x1) > +#define TRC_HW_IRQ_MOVE_CLEANUP (TRC_HW_IRQ + 0x2) > +#define TRC_HW_IRQ_BIND_VECTOR (TRC_HW_IRQ + 0x3) > +#define TRC_HW_IRQ_CLEAR_VECTOR (TRC_HW_IRQ + 0x4) > +#define TRC_HW_IRQ_MOVE_FINISH (TRC_HW_IRQ + 0x5) > +#define TRC_HW_IRQ_ASSIGN_VECTOR (TRC_HW_IRQ + 0x6) > +#define TRC_HW_IRQ_UNMAPPED_VECTOR (TRC_HW_IRQ + 0x7) > +#define TRC_HW_IRQ_HANDLED (TRC_HW_IRQ + 0x8) > + > +/* > + * Event Flags > + * > + * Some events (e.g, TRC_PV_TRAP and TRC_HVM_IOMEM_READ) have > multiple > + * record formats. These event flags distinguish between the > + * different formats. > + */ > +#define TRC_64_FLAG 0x100 /* Addresses are 64 bits (instead of 32 bits) */ > + > +/* This structure represents a single trace buffer record. */ > +struct t_rec { > + uint32_t event:28; > + uint32_t extra_u32:3; /* # entries in trailing extra_u32[] array > */ > + uint32_t cycles_included:1; /* u.cycles or u.no_cycles? */ > + union { > + struct { > + uint32_t cycles_lo, cycles_hi; /* cycle counter timestamp */ > + uint32_t extra_u32[7]; /* event data items */ > + } cycles; > + struct { > + uint32_t extra_u32[7]; /* event data items */ > + } nocycles; > + } u; > +}; > + > +/* > + * This structure contains the metadata for a single trace buffer. The head > + * field, indexes into an array of struct t_rec's. > + */ > +struct t_buf { > + /* Assume the data buffer size is X. X is generally not a power of 2. > + * CONS and PROD are incremented modulo (2*X): > + * 0 <= cons < 2*X > + * 0 <= prod < 2*X > + * This is done because addition modulo X breaks at 2^32 when X is not a > + * power of 2: > + * (((2^32 - 1) % X) + 1) % X != (2^32) % X > + */ > + uint32_t cons; /* Offset of next item to be consumed by control tools. > */ > + uint32_t prod; /* Offset of next item to be produced by Xen. > */ > + /* Records follow immediately after the meta-data header. */ > +}; > + > +/* Structure used to pass MFNs to the trace buffers back to trace > consumers. > + * Offset is an offset into the mapped structure where the mfn list will be > held. > + * MFNs will be at ((ULONG_PTR *)(t_info))+(t_info->cpu_offset[cpu]). > + */ > +struct t_info { > + uint16_t tbuf_size; /* Size in pages of each trace buffer */ > + uint16_t mfn_offset[]; /* Offset within t_info structure of the page > list > per cpu */ > + /* MFN lists immediately after the header */ > +}; > + > +#endif /* __XEN_PUBLIC_TRACE_H__ */ > + > +/* > + * Local variables: > + * mode: C > + * c-file-style: "BSD" > + * c-basic-offset: 4 > + * tab-width: 4 > + * indent-tabs-mode: nil > + * End: > + */ > diff --git a/include/xen/public/xen-compat.h b/include/xen/public/xen- > compat.h > new file mode 100755 > index 0000000..2eea0e2 > --- /dev/null > +++ b/include/xen/public/xen-compat.h > @@ -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__ 0x00040700 > + > +#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__ */ > diff --git a/include/xen/public/xen.h b/include/xen/public/xen.h > new file mode 100755 > index 0000000..2057b52 > --- /dev/null > +++ b/include/xen/public/xen.h > @@ -0,0 +1,995 @@ > +/********************************************************* > ********************* > + * 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_PTR); > +__DEFINE_XEN_GUEST_HANDLE(ulong, ULONG_PTR); > +#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); > + > +/* Turn a plain number into a C unsigned (LONG_PTR) constant. */ > +#define __xen_mk_uint(x) x ## U > +#define __xen_mk_ulong(x) x ## UL > +#define xen_mk_uint(x) __xen_mk_uint(x) > +#define xen_mk_ulong(x) __xen_mk_ulong(x) > + > +#else > + > +/* In assembly code we cannot use C numeric constant suffixes. */ > +#define xen_mk_uint(x) x > +#define xen_mk_ulong(x) x > + > +#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 */ > +#define __HYPERVISOR_xenpmu_op 40 > + > +/* 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 */ > +#define VIRQ_XENPMU 13 /* V. PMC interrupt > */ > + > +/* 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 */ > + ULONG_PTR 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(ULONG_PTR va, u64 val, > + * ` enum uvm_flags flags) > + * ` > + * ` enum neg_errnoval > + * ` HYPERVISOR_update_va_mapping_otherdomain(ULONG_PTR 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 (xen_mk_ulong(0)<<0) /* No flushing at all. */ > +#define UVMF_TLB_FLUSH (xen_mk_ulong(1)<<0) /* Flush entire TLB(s). > */ > +#define UVMF_INVLPG (xen_mk_ulong(2)<<0) /* Flush only one entry. > */ > +#define UVMF_FLUSHTYPE_MASK (xen_mk_ulong(3)<<0) > +#define UVMF_MULTI (xen_mk_ulong(0)<<2) /* Flush subset of TLBs. > */ > +#define UVMF_LOCAL (xen_mk_ulong(0)<<2) /* Flush local TLB. */ > +#define UVMF_ALL (xen_mk_ulong(1)<<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 > + > +/* > + * x86 guests: Sane behaviour for virtual iopl > + * - virtual iopl updated from do_iret() hypercalls. > + * - virtual iopl reported in bounce frames. > + * - guest kernels assumed to be level 0 for the purpose of iopl checks. > + */ > +#define VMASST_TYPE_architectural_iopl 4 > + > +/* > + * x86/64 guests: strictly hide M2P from user mode. > + * This allows the guest to control respective hypervisor behavior: > + * - when not set, L4 tables get created with the respective slot blank, > + * and whenever the L4 table gets used as a kernel one the missing > + * mapping gets inserted, > + * - when set, L4 tables get created with the respective slot initialized > + * as before, and whenever the L4 table gets used as a user one the > + * mapping gets zapped. > + */ > +#define VMASST_TYPE_m2p_strict 32 > + > +#if __XEN_INTERFACE_VERSION__ < 0x00040600 > +#define MAX_VMASST_TYPE 3 > +#endif > + > +/* Domain ids >= DOMID_FIRST_RESERVED cannot be used for ordinary > domains. */ > +#define DOMID_FIRST_RESERVED xen_mk_uint(0x7FF0) > + > +/* DOMID_SELF is used in certain contexts to refer to oneself. */ > +#define DOMID_SELF xen_mk_uint(0x7FF0) > + > +/* > + * 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 xen_mk_uint(0x7FF1) > + > +/* > + * 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 xen_mk_uint(0x7FF2) > + > +/* > + * DOMID_COW is used as the owner of sharable pages */ > +#define DOMID_COW xen_mk_uint(0x7FF3) > + > +/* DOMID_INVALID is used to identify pages with unknown owner. */ > +#define DOMID_INVALID xen_mk_uint(0x7FF4) > + > +/* Idle domain. */ > +#define DOMID_IDLE xen_mk_uint(0x7FFF) > + > +#ifndef __ASSEMBLY__ > + > +typedef uint16_t domid_t; > + > +/* > + * 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_PTR is 32 bits; 4096 if a LONG_PTR 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; > +#if __XEN_INTERFACE_VERSION__ > 0x040600 > + uint8_t flags; > + uint8_t pad1[2]; > +#else > + int8_t pad1[3]; > +#endif > +}; /* 32 bytes */ > +typedef struct vcpu_time_info vcpu_time_info_t; > + > +#define XEN_PVCLOCK_TSC_STABLE_BIT (1 << 0) > +#define XEN_PVCLOCK_GUEST_STOPPED (1 << 1) > + > +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_PTR' 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. */ > +#if !defined(__i386__) > + uint32_t wc_sec_hi; > +# define xen_wc_sec_hi wc_sec_hi > +#elif !defined(__XEN__) && !defined(__XEN_TOOLS__) > +# define xen_wc_sec_hi arch.wc_sec_hi > +#endif > + > + 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] > + * (may be omitted) > + * 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)] > + * in case of dom0 this page contains the console info, too > + * e. unless dom0: xenstore ring page > + * f. unless dom0: console ring page > + * g. bootstrap page tables [pt_base and CR3 (x86)] > + * h. bootstrap stack [register ESP (x86)] > + * 4. Bootstrap elements are packed together, but each is 4kB-aligned. > + * 5. 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. > + * 6. All bootstrap elements are mapped read-writable for the guest OS. > The > + * only exception is the bootstrap page table, which is mapped read-only. > + * 7. 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.g 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>". */ > + ULONG_PTR nr_pages; /* Total pages allocated to this domain. */ > + ULONG_PTR 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). > */ > + ULONG_PTR pt_base; /* VIRTUAL address of page directory. */ > + ULONG_PTR nr_pt_frames; /* Number of bootstrap p.t. frames. */ > + ULONG_PTR mfn_list; /* VIRTUAL address of page-frame list. */ > + ULONG_PTR mod_start; /* VIRTUAL address of pre-loaded module */ > + /* (PFN of pre-loaded module if */ > + /* SIF_MOD_START_PFN set in flags). */ > + ULONG_PTR 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. */ > + ULONG_PTR first_p2m_pfn;/* 1st pfn forming initial P->M table. */ > + ULONG_PTR nr_p2m_frames;/* # of pfns forming initial P->M table. */ > +}; > +typedef struct start_info start_info_t; > + > +/* > + * Start of day structure passed to PVH guests in %ebx. > + * > + * NOTE: nothing will be loaded at physical address 0, so a 0 value in any > + * of the address fields should be treated as not present. > + * > + * 0 +----------------+ > + * | magic | Contains the magic value > XEN_HVM_START_MAGIC_VALUE > + * | | ("xEn3" with the 0x80 bit of the "E" set). > + * 4 +----------------+ > + * | version | Version of this structure. Current version is 0. New > + * | | versions are guaranteed to be backwards-compatible. > + * 8 +----------------+ > + * | flags | SIF_xxx flags. > + * 12 +----------------+ > + * | nr_modules | Number of modules passed to the kernel. > + * 16 +----------------+ > + * | modlist_paddr | Physical address of an array of modules > + * | | (layout of the structure below). > + * 24 +----------------+ > + * | cmdline_paddr | Physical address of the command line, > + * | | a zero-terminated ASCII string. > + * 32 +----------------+ > + * | rsdp_paddr | Physical address of the RSDP ACPI data structure. > + * 40 +----------------+ > + * > + * The layout of each entry in the module structure is the following: > + * > + * 0 +----------------+ > + * | paddr | Physical address of the module. > + * 8 +----------------+ > + * | size | Size of the module in bytes. > + * 16 +----------------+ > + * | cmdline_paddr | Physical address of the command line, > + * | | a zero-terminated ASCII string. > + * 24 +----------------+ > + * | reserved | > + * 32 +----------------+ > + * > + * The address and sizes are always a 64bit little endian unsigned integer. > + * > + * NB: Xen on x86 will always try to place all the data below the 4GiB > + * boundary. > + */ > +#define XEN_HVM_START_MAGIC_VALUE 0x336ec578 > + > +/* 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_VIRT_P2M_4TOOLS (1<<4) /* Do Xen tools understand a virt. > mapped */ > + /* P->M making the 3 level tree obsolete? > */ > +#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]; > + > +__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); > + > +#endif /* !__ASSEMBLY__ */ > + > +/* Default definitions for macros used by domctl/sysctl. */ > +#if defined(__XEN__) || defined(__XEN_TOOLS__) > + > +#ifndef int64_aligned_t > +#define int64_aligned_t int64_t > +#endif > +#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: > + */ > diff --git a/include/xen/xen/errno.h b/include/xen/xen/errno.h > new file mode 100755 > index 0000000..69b28dd > --- /dev/null > +++ b/include/xen/xen/errno.h > @@ -0,0 +1,18 @@ > +#ifndef __XEN_ERRNO_H__ > +#define __XEN_ERRNO_H__ > + > +#ifndef __ASSEMBLY__ > + > +#define XEN_ERRNO(name, value) name = value, > +enum { > +#include <public/errno.h> > +}; > + > +#else /* !__ASSEMBLY__ */ > + > +#define XEN_ERRNO(name, value) .equ name, value > +#include <public/errno.h> > + > +#endif /* __ASSEMBLY__ */ > + > +#endif /* __XEN_ERRNO_H__ */ > diff --git a/src/xencons/fdo.c b/src/xencons/fdo.c > index 4046acf..e28355c 100644 > --- a/src/xencons/fdo.c > +++ b/src/xencons/fdo.c > @@ -734,8 +734,10 @@ __FdoEnumerate( > > // If the PDO is the default console, it wont exist in the > // the device list, as its statically created > - if (PdoIsDefault(Pdo)) > + if (PdoIsDefault(Pdo)) { > + ListEntry = Next; > continue; > + } > > if (PdoGetDevicePnpState(Pdo) != Deleted) { > PCHAR Name; > diff --git a/src/xencons/frontend.c b/src/xencons/frontend.c > new file mode 100755 > index 0000000..bdd2945 > --- /dev/null > +++ b/src/xencons/frontend.c > @@ -0,0 +1,1499 @@ > +/* Copyright (c) Citrix Systems Inc. > +* All rights reserved. > +* > +* Redistribution and use in source and binary forms, > +* with or without modification, are permitted provided > +* that the following conditions are met: > +* > +* * Redistributions of source code must retain the above > +* copyright notice, this list of conditions and the > +* following disclaimer. > +* * Redistributions in binary form must reproduce the above > +* copyright notice, this list of conditions and the > +* following disclaimer in the documentation and/or other > +* materials provided with the distribution. > +* > +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND > +* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, > +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF > +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE > +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR > +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, > +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, > +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR > +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS > +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, > +* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING > +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE > +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF > +* SUCH DAMAGE. > +*/ > + > +#define INITGUID 1 > + > +#include <ntddk.h> > +#include <wdmguid.h> > +#include <ntstrsafe.h> > +#include <stdlib.h> > + > +#include <xen.h> > +#include <store_interface.h> > +#include <suspend_interface.h> > +#include <debug_interface.h> > +#include <xencons_device.h> > + > +#include "driver.h" > +#include "frontend.h" > +#include "thread.h" > +#include "dbg_print.h" > +#include "assert.h" > +#include "util.h" > + > +#define FRONTEND_POOL 'TNRF' > +#define DOMID_INVALID (0x7FFFU) > + > +typedef enum _FRONTEND_STATE { > + FRONTEND_UNKNOWN, > + FRONTEND_CLOSED, > + FRONTEND_PREPARED, > + FRONTEND_CONNECTED, > + FRONTEND_ENABLED > +} FRONTEND_STATE, *PFRONTEND_STATE; > + > +struct _XENCONS_FRONTEND { > + LONG RefCount; > + PXENCONS_PDO Pdo; > + PCHAR Path; > + FRONTEND_STATE State; > + KSPIN_LOCK Lock; > + PXENCONS_THREAD EjectThread; > + KEVENT EjectEvent; > + BOOLEAN Online; > + > + PCHAR BackendPath; > + USHORT BackendDomain; > + PCHAR Name; > + PCHAR Protocol; > + > + XENBUS_DEBUG_INTERFACE DebugInterface; > + XENBUS_SUSPEND_INTERFACE SuspendInterface; > + XENBUS_STORE_INTERFACE StoreInterface; > + > + PXENBUS_SUSPEND_CALLBACK SuspendCallback; > + PXENBUS_DEBUG_CALLBACK DebugCallback; > + PXENBUS_STORE_WATCH Watch; > +}; > + > +static const PCHAR > +FrontendStateName( > + IN FRONTEND_STATE State > + ) > +{ > +#define _STATE_NAME(_State) \ > + case FRONTEND_ ## _State: \ > + return #_State; > + > + switch (State) { > + _STATE_NAME(UNKNOWN); > + _STATE_NAME(CLOSED); > + _STATE_NAME(PREPARED); > + _STATE_NAME(CONNECTED); > + _STATE_NAME(ENABLED); > + default: > + break; > + } > + > + return "INVALID"; > + > +#undef _STATE_NAME > +} > + > +static const PCHAR > +XenbusStateName( > + IN XenbusState State > + ) > +{ > +#define _STATE_NAME(_State) \ > + case XenbusState ## _State: \ > + return #_State; > + > + switch (State) { > + _STATE_NAME(Unknown); > + _STATE_NAME(Initialising); > + _STATE_NAME(InitWait); > + _STATE_NAME(Initialised); > + _STATE_NAME(Connected); > + _STATE_NAME(Closing); > + _STATE_NAME(Closed); > + _STATE_NAME(Reconfiguring); > + _STATE_NAME(Reconfigured); > + default: > + break; > + } > + > + return "INVALID"; > + > +#undef _STATE_NAME > +} > + > +static FORCEINLINE PVOID > +__FrontendAllocate( > + IN ULONG Length > + ) > +{ > + return __AllocatePoolWithTag(NonPagedPool, Length, > FRONTEND_POOL); > +} > + > +static FORCEINLINE VOID > +__FrontendFree( > + IN PVOID Buffer > + ) > +{ > + __FreePoolWithTag(Buffer, FRONTEND_POOL); > +} > + > +static FORCEINLINE PXENCONS_PDO > +__FrontendGetPdo( > + IN PXENCONS_FRONTEND Frontend > + ) > +{ > + return Frontend->Pdo; > +} > + > +PXENCONS_PDO > +FrontendGetPdo( > + IN PXENCONS_FRONTEND Frontend > + ) > +{ > + return __FrontendGetPdo(Frontend); > +} > + > +static FORCEINLINE PCHAR > +__FrontendGetPath( > + IN PXENCONS_FRONTEND Frontend > + ) > +{ > + return Frontend->Path; > +} > + > +PCHAR > +FrontendGetPath( > + IN PXENCONS_FRONTEND Frontend > + ) > +{ > + return __FrontendGetPath(Frontend); > +} > + > +static FORCEINLINE PCHAR > +__FrontendGetBackendPath( > + IN PXENCONS_FRONTEND Frontend > + ) > +{ > + return Frontend->BackendPath; > +} > + > +PCHAR > +FrontendGetBackendPath( > + IN PXENCONS_FRONTEND Frontend > + ) > +{ > + return __FrontendGetBackendPath(Frontend); > +} > + > +static FORCEINLINE USHORT > +__FrontendGetBackendDomain( > + IN PXENCONS_FRONTEND Frontend > + ) > +{ > + return Frontend->BackendDomain; > +} > + > +USHORT > +FrontendGetBackendDomain( > + IN PXENCONS_FRONTEND Frontend > + ) > +{ > + return __FrontendGetBackendDomain(Frontend); > +} > + > +static BOOLEAN > +FrontendIsOnline( > + IN PXENCONS_FRONTEND Frontend > + ) > +{ > + return Frontend->Online; > +} > + > +static BOOLEAN > +FrontendIsBackendOnline( > + IN PXENCONS_FRONTEND Frontend > + ) > +{ > + PCHAR Buffer; > + BOOLEAN Online; > + NTSTATUS status; > + > + status = XENBUS_STORE(Read, > + &Frontend->StoreInterface, > + NULL, > + __FrontendGetBackendPath(Frontend), > + "online", > + &Buffer); > + if (!NT_SUCCESS(status)) { > + Online = FALSE; > + } else { > + Online = (BOOLEAN)strtol(Buffer, NULL, 2); > + > + XENBUS_STORE(Free, > + &Frontend->StoreInterface, > + Buffer); > + } > + > + return Online; > +} > + > +static DECLSPEC_NOINLINE NTSTATUS > +FrontendEject( > + IN PXENCONS_THREAD Self, > + IN PVOID Context > + ) > +{ > + PXENCONS_FRONTEND Frontend = Context; > + PKEVENT Event; > + > + Trace("%s: ====>\n", __FrontendGetPath(Frontend)); > + > + Event = ThreadGetEvent(Self); > + > + for (;;) { > + KIRQL Irql; > + > + KeWaitForSingleObject(Event, > + Executive, > + KernelMode, > + FALSE, > + NULL); > + KeClearEvent(Event); > + > + if (ThreadIsAlerted(Self)) > + break; > + > + KeAcquireSpinLock(&Frontend->Lock, &Irql); > + > + // It is not safe to use interfaces before this point > + if (Frontend->State == FRONTEND_UNKNOWN || > + Frontend->State == FRONTEND_CLOSED) > + goto loop; > + > + if (!FrontendIsOnline(Frontend)) > + goto loop; > + > + if (!FrontendIsBackendOnline(Frontend)) > + PdoRequestEject(__FrontendGetPdo(Frontend)); > + > + loop: > + KeReleaseSpinLock(&Frontend->Lock, Irql); > + > + KeSetEvent(&Frontend->EjectEvent, IO_NO_INCREMENT, FALSE); > + } > + > + KeSetEvent(&Frontend->EjectEvent, IO_NO_INCREMENT, FALSE); > + > + Trace("%s: <====\n", __FrontendGetPath(Frontend)); > + > + return STATUS_SUCCESS; > +} > + > +VOID > +FrontendEjectFailed( > + IN PXENCONS_FRONTEND Frontend > + ) > +{ > + KIRQL Irql; > + ULONG Length; > + PCHAR Path; > + NTSTATUS status; > + > + KeAcquireSpinLock(&Frontend->Lock, &Irql); > + > + Info("%s: device eject failed\n", __FrontendGetPath(Frontend)); > + > + Length = sizeof("error/") + > (ULONG)strlen(__FrontendGetPath(Frontend)); > + Path = __FrontendAllocate(Length); > + > + status = STATUS_NO_MEMORY; > + if (Path == NULL) > + goto fail1; > + > + status = RtlStringCbPrintfA(Path, > + Length, > + "error/%s", > + __FrontendGetPath(Frontend)); > + if (!NT_SUCCESS(status)) > + goto fail2; > + > + (VOID)XENBUS_STORE(Printf, > + &Frontend->StoreInterface, > + NULL, > + Path, > + "error", > + "UNPLUG FAILED: device is still in use"); > + > + __FrontendFree(Path); > + > + KeReleaseSpinLock(&Frontend->Lock, Irql); > + return; > + > +fail2: > + Error("fail2\n"); > + > + __FrontendFree(Path); > + > +fail1: > + Error("fail1 (%08x)\n", status); > + > + KeReleaseSpinLock(&Frontend->Lock, Irql); > +} > + > +static VOID > +FrontendSetOnline( > + IN PXENCONS_FRONTEND Frontend > + ) > +{ > + Trace("====>\n"); > + > + Frontend->Online = TRUE; > + > + Trace("<====\n"); > +} > + > +static VOID > +FrontendSetOffline( > + IN PXENCONS_FRONTEND Frontend > + ) > +{ > + Trace("====>\n"); > + > + Frontend->Online = FALSE; > + PdoRequestEject(__FrontendGetPdo(Frontend)); > + > + Trace("<====\n"); > +} > + > +static VOID > +FrontendSetXenbusState( > + IN PXENCONS_FRONTEND Frontend, > + IN XenbusState State > + ) > +{ > + BOOLEAN Online; > + > + Trace("%s: ====> %s\n", > + __FrontendGetPath(Frontend), > + XenbusStateName(State)); > + > + ASSERT(FrontendIsOnline(Frontend)); > + > + Online = FrontendIsBackendOnline(Frontend); > + > + (VOID)XENBUS_STORE(Printf, > + &Frontend->StoreInterface, > + NULL, > + __FrontendGetPath(Frontend), > + "state", > + "%u", > + State); > + > + if (State == XenbusStateClosed && !Online) > + FrontendSetOffline(Frontend); > + > + Trace("%s: <==== %s\n", > + __FrontendGetPath(Frontend), > + XenbusStateName(State)); > +} > + > +static VOID > +FrontendWaitForBackendXenbusStateChange( > + IN PXENCONS_FRONTEND Frontend, > + IN OUT XenbusState *State > + ) > +{ > + KEVENT Event; > + PXENBUS_STORE_WATCH Watch; > + LARGE_INTEGER Start; > + ULONGLONG TimeDelta; > + LARGE_INTEGER Timeout; > + XenbusState Old = *State; > + NTSTATUS status; > + > + Trace("%s: ====> %s\n", > + __FrontendGetBackendPath(Frontend), > + XenbusStateName(*State)); > + > + ASSERT(FrontendIsOnline(Frontend)); > + > + KeInitializeEvent(&Event, NotificationEvent, FALSE); > + > + status = XENBUS_STORE(WatchAdd, > + &Frontend->StoreInterface, > + __FrontendGetBackendPath(Frontend), > + "state", > + &Event, > + &Watch); > + if (!NT_SUCCESS(status)) > + Watch = NULL; > + > + KeQuerySystemTime(&Start); > + TimeDelta = 0; > + > + Timeout.QuadPart = 0; > + > + while (*State == Old && TimeDelta < 120000) { > + PCHAR Buffer; > + LARGE_INTEGER Now; > + > + if (Watch != NULL) { > + ULONG Attempt = 0; > + > + while (++Attempt < 1000) { > + status = KeWaitForSingleObject(&Event, > + Executive, > + KernelMode, > + FALSE, > + &Timeout); > + if (status != STATUS_TIMEOUT) > + break; > + > + // We are waiting for a watch event at DISPATCH_LEVEL so > + // it is our responsibility to poll the store ring. > + XENBUS_STORE(Poll, > + &Frontend->StoreInterface); > + > + KeStallExecutionProcessor(1000); // 1ms > + } > + > + KeClearEvent(&Event); > + } > + > + status = XENBUS_STORE(Read, > + &Frontend->StoreInterface, > + NULL, > + __FrontendGetBackendPath(Frontend), > + "state", > + &Buffer); > + if (!NT_SUCCESS(status)) { > + *State = XenbusStateUnknown; > + } else { > + *State = (XenbusState)strtol(Buffer, NULL, 10); > + > + XENBUS_STORE(Free, > + &Frontend->StoreInterface, > + Buffer); > + } > + > + KeQuerySystemTime(&Now); > + > + TimeDelta = (Now.QuadPart - Start.QuadPart) / 10000ull; > + } > + > + if (Watch != NULL) > + (VOID) XENBUS_STORE(WatchRemove, > + &Frontend->StoreInterface, > + Watch); > + > + Trace("%s: <==== (%s)\n", > + __FrontendGetBackendPath(Frontend), > + XenbusStateName(*State)); > +} > + > +static NTSTATUS > +FrontendAcquireBackend( > + IN PXENCONS_FRONTEND Frontend > + ) > +{ > + PCHAR Buffer; > + NTSTATUS status; > + > + Trace("=====>\n"); > + > + status = XENBUS_STORE(Read, > + &Frontend->StoreInterface, > + NULL, > + __FrontendGetPath(Frontend), > + "backend", > + &Buffer); > + if (!NT_SUCCESS(status)) > + goto fail1; > + > + Frontend->BackendPath = Buffer; > + > + status = XENBUS_STORE(Read, > + &Frontend->StoreInterface, > + NULL, > + __FrontendGetPath(Frontend), > + "backend-id", > + &Buffer); > + if (!NT_SUCCESS(status)) { > + Frontend->BackendDomain = 0; > + } else { > + Frontend->BackendDomain = (USHORT)strtol(Buffer, NULL, 10); > + > + XENBUS_STORE(Free, > + &Frontend->StoreInterface, > + Buffer); > + } > + > + return STATUS_SUCCESS; > + > +fail1: > + Error("fail1 (%08x)\n", status); > + > + Trace("<====\n"); > + return status; > +} > + > +static VOID > +FrontendReleaseBackend( > + IN PXENCONS_FRONTEND Frontend > + ) > +{ > + Trace("=====>\n"); > + > + ASSERT(Frontend->BackendDomain != DOMID_INVALID); > + ASSERT(Frontend->BackendPath != NULL); > + > + Frontend->BackendDomain = DOMID_INVALID; > + > + XENBUS_STORE(Free, > + &Frontend->StoreInterface, > + Frontend->BackendPath); > + Frontend->BackendPath = NULL; > + > + Trace("<=====\n"); > +} > + > +static VOID > +FrontendClose( > + IN PXENCONS_FRONTEND Frontend > + ) > +{ > + XenbusState State; > + > + Trace("====>\n"); > + > + ASSERT(Frontend->Watch != NULL); > + (VOID)XENBUS_STORE(WatchRemove, > + &Frontend->StoreInterface, > + Frontend->Watch); > + Frontend->Watch = NULL; > + > + State = XenbusStateUnknown; > + while (State != XenbusStateClosed) { > + if (!FrontendIsOnline(Frontend)) > + break; > + > + FrontendSetXenbusState(Frontend, > + XenbusStateClosed); > + > + FrontendWaitForBackendXenbusStateChange(Frontend, > + &State); > + } > + > + FrontendReleaseBackend(Frontend); > + > + XENBUS_STORE(Release, &Frontend->StoreInterface); > + > + Trace("<====\n"); > +} > + > +static NTSTATUS > +FrontendPrepare( > + IN PXENCONS_FRONTEND Frontend > + ) > +{ > + XenbusState State; > + NTSTATUS status; > + > + Trace("====>\n"); > + > + status = XENBUS_STORE(Acquire, &Frontend->StoreInterface); > + if (!NT_SUCCESS(status)) > + goto fail1; > + > + FrontendSetOnline(Frontend); > + > + status = FrontendAcquireBackend(Frontend); > + if (!NT_SUCCESS(status)) > + goto fail2; > + > + State = XenbusStateUnknown; > + while (State != XenbusStateInitWait) { > + if (!FrontendIsOnline(Frontend)) > + break; > + > + FrontendSetXenbusState(Frontend, > + XenbusStateInitialising); > + > + FrontendWaitForBackendXenbusStateChange(Frontend, > + &State); > + } > + > + status = STATUS_UNSUCCESSFUL; > + if (State != XenbusStateInitWait) > + goto fail3; > + > + status = XENBUS_STORE(WatchAdd, > + &Frontend->StoreInterface, > + __FrontendGetBackendPath(Frontend), > + "online", > + ThreadGetEvent(Frontend->EjectThread), > + &Frontend->Watch); > + if (!NT_SUCCESS(status)) > + goto fail4; > + > + Trace("<====\n"); > + return STATUS_SUCCESS; > + > +fail4: > + Error("fail4\n"); > + > +fail3: > + Error("fail3\n"); > + > + FrontendReleaseBackend(Frontend); > + > +fail2: > + Error("fail2\n"); > + > + FrontendSetOffline(Frontend); > + > + XENBUS_STORE(Release, &Frontend->StoreInterface); > + > +fail1: > + Error("fail1 (%08x)\n", status); > + > + return status; > +} > + > +static VOID > +FrontendDebugCallback( > + IN PVOID Argument, > + IN BOOLEAN Crashing > + ) > +{ > + PXENCONS_FRONTEND Frontend = Argument; > + > + UNREFERENCED_PARAMETER(Crashing); > + > + XENBUS_DEBUG(Printf, > + &Frontend->DebugInterface, > + "PATH: %s\n", > + __FrontendGetPath(Frontend)); > + XENBUS_DEBUG(Printf, > + &Frontend->DebugInterface, > + "NAME: %s\n", > + Frontend->Name); > + XENBUS_DEBUG(Printf, > + &Frontend->DebugInterface, > + "PROTOCOL: %s\n", > + Frontend->Protocol); > +} > + > +static NTSTATUS > +FrontendConnect( > + IN PXENCONS_FRONTEND Frontend > + ) > +{ > + XenbusState State; > + ULONG Attempt; > + PCHAR Buffer; > + ULONG Length; > + NTSTATUS status; > + > + Trace("====>\n"); > + > + status = XENBUS_DEBUG(Acquire, &Frontend->DebugInterface); > + if (!NT_SUCCESS(status)) > + goto fail1; > + > + status = XENBUS_DEBUG(Register, > + &Frontend->DebugInterface, > + __MODULE__ "|FRONTEND", > + FrontendDebugCallback, > + Frontend, > + &Frontend->DebugCallback); > + if (!NT_SUCCESS(status)) > + goto fail2; > + > + // TODO: Connect Ring > + > + Attempt = 0; > + do { > + PXENBUS_STORE_TRANSACTION Transaction; > + > + status = XENBUS_STORE(TransactionStart, > + &Frontend->StoreInterface, > + &Transaction); > + if (!NT_SUCCESS(status)) > + break; > + > + // TODO: StoreWrite Ring > + > + status = XENBUS_STORE(TransactionEnd, > + &Frontend->StoreInterface, > + Transaction, > + TRUE); > + if (status != STATUS_RETRY || ++Attempt > 10) > + break; > + > + continue; > + > + //abort: > + // (VOID)XENBUS_STORE(TransactionEnd, > + // &Frontend->StoreInterface, > + // Transaction, > + // FALSE); > + // break; > + } while (status == STATUS_RETRY); > + > + if (!NT_SUCCESS(status)) > + goto fail4; > + > + State = XenbusStateUnknown; > + while (State != XenbusStateConnected) { > + if (!FrontendIsOnline(Frontend)) > + break; > + > + FrontendSetXenbusState(Frontend, > + XenbusStateConnected); > + > + FrontendWaitForBackendXenbusStateChange(Frontend, > + &State); > + } > + > + status = STATUS_UNSUCCESSFUL; > + if (State != XenbusStateConnected) > + goto fail5; > + > + status = XENBUS_STORE(Read, > + &Frontend->StoreInterface, > + NULL, > + __FrontendGetBackendPath(Frontend), > + "name", > + &Buffer); > + if (NT_SUCCESS(status)) { > + Length = (ULONG)strlen(Buffer); > + > + Frontend->Name = __FrontendAllocate(Length); > + if (Frontend->Name) > + RtlCopyMemory(Frontend->Name, Buffer, Length); > + > + XENBUS_STORE(Free, > + &Frontend->StoreInterface, > + Buffer); > + } > + > + status = XENBUS_STORE(Read, > + &Frontend->StoreInterface, > + NULL, > + __FrontendGetBackendPath(Frontend), > + "protocol", > + &Buffer); > + if (NT_SUCCESS(status)) { > + Length = (ULONG)strlen(Buffer); > + > + Frontend->Protocol = __FrontendAllocate(Length); > + if (Frontend->Protocol) > + RtlCopyMemory(Frontend->Protocol, Buffer, Length); > + > + XENBUS_STORE(Free, > + &Frontend->StoreInterface, > + Buffer); > + } > + > + Trace("<====\n"); > + return STATUS_SUCCESS; > + > +fail5: > + Error("fail5\n"); > + > +fail4: > + Error("fail4\n"); > + > +//fail3: > + Error("fail3\n"); > + > +fail2: > + Error("fail2\n"); > + > +fail1: > + Error("fail1 (%08x)\n", status); > + > + return status; > +} > + > +static VOID > +FrontendDisconnect( > + IN PXENCONS_FRONTEND Frontend > + ) > +{ > + Trace("====>\n"); > + > + __FrontendFree(Frontend->Protocol); > + Frontend->Protocol = NULL; > + > + __FrontendFree(Frontend->Name); > + Frontend->Name = NULL; > + > + // TODO: Disconnect Ring > + > + XENBUS_DEBUG(Deregister, > + &Frontend->DebugInterface, > + Frontend->DebugCallback); > + Frontend->DebugCallback = NULL; > + > + XENBUS_DEBUG(Release, &Frontend->DebugInterface); > + > + Trace("<====\n"); > +} > + > +static NTSTATUS > +FrontendEnable( > + IN PXENCONS_FRONTEND Frontend > + ) > +{ > + Trace("====>\n"); > + > + UNREFERENCED_PARAMETER(Frontend); > + // TODO: Enable Ring > + > + Trace("<====\n"); > + > + return STATUS_SUCCESS; > +} > + > +static VOID > +FrontendDisable( > + IN PXENCONS_FRONTEND Frontend > + ) > +{ > + Trace("====>\n"); > + > + UNREFERENCED_PARAMETER(Frontend); > + // TODO: Disable Ring > + > + Trace("<====\n"); > +} > + > +static NTSTATUS > +FrontendSetState( > + IN PXENCONS_FRONTEND Frontend, > + IN FRONTEND_STATE State > + ) > +{ > + BOOLEAN Failed; > + KIRQL Irql; > + > + KeAcquireSpinLock(&Frontend->Lock, &Irql); > + > + Info("%s: ====> '%s' -> '%s'\n", > + __FrontendGetPath(Frontend), > + FrontendStateName(Frontend->State), > + FrontendStateName(State)); > + > + Failed = FALSE; > + while (Frontend->State != State && !Failed) { > + NTSTATUS status; > + > + switch (Frontend->State) { > + case FRONTEND_UNKNOWN: > + switch (State) { > + case FRONTEND_CLOSED: > + case FRONTEND_PREPARED: > + case FRONTEND_CONNECTED: > + case FRONTEND_ENABLED: > + status = FrontendPrepare(Frontend); > + if (NT_SUCCESS(status)) { > + Frontend->State = FRONTEND_PREPARED; > + } else { > + Failed = TRUE; > + } > + break; > + > + default: > + ASSERT(FALSE); > + break; > + } > + break; > + > + case FRONTEND_CLOSED: > + switch (State) { > + case FRONTEND_PREPARED: > + case FRONTEND_CONNECTED: > + case FRONTEND_ENABLED: > + status = FrontendPrepare(Frontend); > + if (NT_SUCCESS(status)) { > + Frontend->State = FRONTEND_PREPARED; > + } else { > + Failed = TRUE; > + } > + break; > + > + case FRONTEND_UNKNOWN: > + Frontend->State = FRONTEND_UNKNOWN; > + break; > + > + default: > + ASSERT(FALSE); > + break; > + } > + break; > + > + case FRONTEND_PREPARED: > + switch (State) { > + case FRONTEND_CONNECTED: > + case FRONTEND_ENABLED: > + status = FrontendConnect(Frontend); > + if (NT_SUCCESS(status)) { > + Frontend->State = FRONTEND_CONNECTED; > + } else { > + FrontendClose(Frontend); > + Frontend->State = FRONTEND_CLOSED; > + > + Failed = TRUE; > + } > + break; > + > + case FRONTEND_CLOSED: > + case FRONTEND_UNKNOWN: > + FrontendClose(Frontend); > + Frontend->State = FRONTEND_CLOSED; > + break; > + > + default: > + ASSERT(FALSE); > + break; > + } > + break; > + > + case FRONTEND_CONNECTED: > + switch (State) { > + case FRONTEND_ENABLED: > + status = FrontendEnable(Frontend); > + if (NT_SUCCESS(status)) { > + Frontend->State = FRONTEND_ENABLED; > + } else { > + FrontendClose(Frontend); > + Frontend->State = FRONTEND_CLOSED; > + > + FrontendDisconnect(Frontend); > + Failed = TRUE; > + } > + break; > + > + case FRONTEND_PREPARED: > + case FRONTEND_CLOSED: > + case FRONTEND_UNKNOWN: > + FrontendClose(Frontend); > + Frontend->State = FRONTEND_CLOSED; > + > + FrontendDisconnect(Frontend); > + break; > + > + default: > + ASSERT(FALSE); > + break; > + } > + break; > + > + case FRONTEND_ENABLED: > + switch (State) { > + case FRONTEND_CONNECTED: > + case FRONTEND_PREPARED: > + case FRONTEND_CLOSED: > + case FRONTEND_UNKNOWN: > + FrontendDisable(Frontend); > + Frontend->State = FRONTEND_CONNECTED; > + break; > + > + default: > + ASSERT(FALSE); > + break; > + } > + break; > + > + default: > + ASSERT(FALSE); > + break; > + } > + > + Info("%s in state '%s'\n", > + __FrontendGetPath(Frontend), > + FrontendStateName(Frontend->State)); > + } > + > + KeReleaseSpinLock(&Frontend->Lock, Irql); > + > + Info("%s: <=====\n", __FrontendGetPath(Frontend)); > + > + return (!Failed) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL; > +} > + > +static FORCEINLINE VOID > +__FrontendResume( > + IN PXENCONS_FRONTEND Frontend > + ) > +{ > + ASSERT3U(KeGetCurrentIrql(), == , DISPATCH_LEVEL); > + > + ASSERT3U(Frontend->State, == , FRONTEND_UNKNOWN); > + UNREFERENCED_PARAMETER(Frontend); > + //(VOID)FrontendSetState(Frontend, FRONTEND_CLOSED); > +} > + > +static FORCEINLINE VOID > +__FrontendSuspend( > + IN PXENCONS_FRONTEND Frontend > + ) > +{ > + ASSERT3U(KeGetCurrentIrql(), == , DISPATCH_LEVEL); > + > + UNREFERENCED_PARAMETER(Frontend); > + //(VOID)FrontendSetState(Frontend, FRONTEND_UNKNOWN); > +} > + > +static DECLSPEC_NOINLINE VOID > +FrontendSuspendCallback( > + IN PVOID Argument > + ) > +{ > + PXENCONS_FRONTEND Frontend = Argument; > + > + __FrontendSuspend(Frontend); > + __FrontendResume(Frontend); > +} > + > +static NTSTATUS > +FrontendResume( > + IN PXENCONS_FRONTEND Frontend > + ) > +{ > + KIRQL Irql; > + NTSTATUS status; > + > + Trace("====>\n"); > + > + KeRaiseIrql(DISPATCH_LEVEL, &Irql); > + > + status = XENBUS_SUSPEND(Acquire, &Frontend->SuspendInterface); > + if (!NT_SUCCESS(status)) > + goto fail1; > + > + __FrontendResume(Frontend); > + > + status = XENBUS_SUSPEND(Register, > + &Frontend->SuspendInterface, > + SUSPEND_CALLBACK_LATE, > + FrontendSuspendCallback, > + Frontend, > + &Frontend->SuspendCallback); > + if (!NT_SUCCESS(status)) > + goto fail2; > + > + KeLowerIrql(Irql); > + > + KeClearEvent(&Frontend->EjectEvent); > + ThreadWake(Frontend->EjectThread); > + > + Trace("waiting for eject thread\n"); > + > + (VOID)KeWaitForSingleObject(&Frontend->EjectEvent, > + Executive, > + KernelMode, > + FALSE, > + NULL); > + > + Trace("<====\n"); > + > + return STATUS_SUCCESS; > + > +fail2: > + Error("fail2\n"); > + > + __FrontendSuspend(Frontend); > + > + XENBUS_SUSPEND(Release, &Frontend->SuspendInterface); > + > +fail1: > + Error("fail1 (%08x)\n", status); > + > + KeLowerIrql(Irql); > + > + return status; > +} > + > +static VOID > +FrontendSuspend( > + IN PXENCONS_FRONTEND Frontend > + ) > +{ > + KIRQL Irql; > + > + Trace("====>\n"); > + > + KeRaiseIrql(DISPATCH_LEVEL, &Irql); > + > + XENBUS_SUSPEND(Deregister, > + &Frontend->SuspendInterface, > + Frontend->SuspendCallback); > + Frontend->SuspendCallback = NULL; > + > + __FrontendSuspend(Frontend); > + > + XENBUS_SUSPEND(Release, &Frontend->SuspendInterface); > + > + KeLowerIrql(Irql); > + > + KeClearEvent(&Frontend->EjectEvent); > + ThreadWake(Frontend->EjectThread); > + > + Trace("waiting for eject thread\n"); > + > + (VOID)KeWaitForSingleObject(&Frontend->EjectEvent, > + Executive, > + KernelMode, > + FALSE, > + NULL); > + > + Trace("<====\n"); > +} > + > +static VOID > +FrontendDestroy( > + IN PXENCONS_FRONTEND Frontend > + ) > +{ > + Trace("=====>\n"); > + > + ASSERT(Frontend->RefCount == 0); > + ASSERT3U(KeGetCurrentIrql(), == , PASSIVE_LEVEL); > + > + ASSERT(Frontend->State == FRONTEND_UNKNOWN); > + > + ThreadAlert(Frontend->EjectThread); > + ThreadJoin(Frontend->EjectThread); > + Frontend->EjectThread = NULL; > + > + RtlZeroMemory(&Frontend->EjectEvent, sizeof(KEVENT)); > + > + // TODO: Teardown Ring > + > + RtlZeroMemory(&Frontend->StoreInterface, > + sizeof(XENBUS_STORE_INTERFACE)); > + > + RtlZeroMemory(&Frontend->SuspendInterface, > + sizeof(XENBUS_SUSPEND_INTERFACE)); > + > + RtlZeroMemory(&Frontend->DebugInterface, > + sizeof(XENBUS_DEBUG_INTERFACE)); > + > + Frontend->Online = FALSE; > + > + RtlZeroMemory(&Frontend->Lock, sizeof(KSPIN_LOCK)); > + > + Frontend->BackendDomain = 0; > + > + __FrontendFree(Frontend->Path); > + Frontend->Path = NULL; > + > + Frontend->Pdo = NULL; > + > + ASSERT(IsZeroMemory(Frontend, sizeof(XENCONS_FRONTEND))); > + __FrontendFree(Frontend); > + > + Trace("<=====\n"); > +} > + > +static NTSTATUS > +FrontendAbiAcquire( > + IN PXENCONS_CONSOLE_CONTEXT Context > + ) > +{ > + PXENCONS_FRONTEND Frontend = > (PXENCONS_FRONTEND)Context; > + KIRQL Irql; > + NTSTATUS status; > + > + InterlockedIncrement(&Frontend->RefCount); > + > + KeRaiseIrql(DISPATCH_LEVEL, &Irql); > + > + status = XENBUS_SUSPEND(Acquire, &Frontend->SuspendInterface); > + if (!NT_SUCCESS(status)) > + goto fail1; > + > + __FrontendResume(Frontend); > + > + status = XENBUS_SUSPEND(Register, > + &Frontend->SuspendInterface, > + SUSPEND_CALLBACK_LATE, > + FrontendSuspendCallback, > + Frontend, > + &Frontend->SuspendCallback); > + if (!NT_SUCCESS(status)) > + goto fail2; > + > + KeLowerIrql(Irql); > + > + KeClearEvent(&Frontend->EjectEvent); > + ThreadWake(Frontend->EjectThread); > + > + Trace("waiting for eject thread\n"); > + > + (VOID)KeWaitForSingleObject(&Frontend->EjectEvent, > + Executive, > + KernelMode, > + FALSE, > + NULL); > + > + return STATUS_SUCCESS; > + > +fail2: > + Error("fail2\n"); > + > + __FrontendSuspend(Frontend); > + > + XENBUS_SUSPEND(Release, &Frontend->SuspendInterface); > + > +fail1: > + Error("fail1 (%08x)\n", status); > + > + KeLowerIrql(Irql); > + > + InterlockedDecrement(&Frontend->RefCount); > + > + return status; > +} > + > +static VOID > +FrontendAbiRelease( > + IN PXENCONS_CONSOLE_CONTEXT Context > + ) > +{ > + PXENCONS_FRONTEND Frontend = > (PXENCONS_FRONTEND)Context; > + LONG Count; > + KIRQL Irql; > + > + Count = InterlockedDecrement(&Frontend->RefCount); > + > + KeRaiseIrql(DISPATCH_LEVEL, &Irql); > + > + XENBUS_SUSPEND(Deregister, > + &Frontend->SuspendInterface, > + Frontend->SuspendCallback); > + Frontend->SuspendCallback = NULL; > + > + __FrontendSuspend(Frontend); > + > + XENBUS_SUSPEND(Release, &Frontend->SuspendInterface); > + > + KeLowerIrql(Irql); > + > + KeClearEvent(&Frontend->EjectEvent); > + ThreadWake(Frontend->EjectThread); > + > + Trace("waiting for eject thread\n"); > + > + (VOID)KeWaitForSingleObject(&Frontend->EjectEvent, > + Executive, > + KernelMode, > + FALSE, > + NULL); > + > + if (Count == 0) > + FrontendDestroy(Frontend); > +} > + > +static BOOLEAN > +FrontendAbiIsDefault( > + IN PXENCONS_CONSOLE_CONTEXT Context > + ) > +{ > + UNREFERENCED_PARAMETER(Context); > + return FALSE; > +} > + > +static NTSTATUS > +FrontendAbiD3ToD0( > + IN PXENCONS_CONSOLE_CONTEXT Context > + ) > +{ > + PXENCONS_FRONTEND Frontend = > (PXENCONS_FRONTEND)Context; > + > + UNREFERENCED_PARAMETER(Frontend); > + //return FrontendSetState(Frontend, FRONTEND_ENABLED); > + return STATUS_SUCCESS; > +} > + > +static VOID > +FrontendAbiD0ToD3( > + IN PXENCONS_CONSOLE_CONTEXT Context > + ) > +{ > + PXENCONS_FRONTEND Frontend = > (PXENCONS_FRONTEND)Context; > + > + UNREFERENCED_PARAMETER(Frontend); > + //(VOID) FrontendSetState(Frontend, FRONTEND_CLOSED); > +} > + > +static NTSTATUS > +FrontendAbiOpen( > + IN PXENCONS_CONSOLE_CONTEXT Context, > + IN PFILE_OBJECT FileObject > + ) > +{ > + UNREFERENCED_PARAMETER(Context); > + UNREFERENCED_PARAMETER(FileObject); > + return STATUS_SUCCESS; > +} > + > +static NTSTATUS > +FrontendAbiClose( > + IN PXENCONS_CONSOLE_CONTEXT Context, > + IN PFILE_OBJECT FileObject > + ) > +{ > + UNREFERENCED_PARAMETER(Context); > + UNREFERENCED_PARAMETER(FileObject); > + return STATUS_SUCCESS; > +} > + > +static NTSTATUS > +FrontendAbiPutQueue( > + IN PXENCONS_CONSOLE_CONTEXT Context, > + IN PIRP Irp > + ) > +{ > + UNREFERENCED_PARAMETER(Context); > + UNREFERENCED_PARAMETER(Irp); > + return STATUS_DEVICE_NOT_READY; > +} > + > +static XENCONS_CONSOLE_ABI FrontendAbiV1 = { > + NULL, > + FrontendAbiAcquire, > + FrontendAbiRelease, > + FrontendAbiIsDefault, > + FrontendAbiD3ToD0, > + FrontendAbiD0ToD3, > + FrontendAbiOpen, > + FrontendAbiClose, > + FrontendAbiPutQueue > +}; > + > +NTSTATUS > +FrontendCreate( > + IN PXENCONS_PDO Pdo, > + IN PXENCONS_CONSOLE_ABI ConsoleAbi > + ) > +{ > + PCHAR Name; > + ULONG Length; > + PCHAR Path; > + PXENCONS_FRONTEND Frontend; > + NTSTATUS status; > + > + Trace("====>\n"); > + > + Name = PdoGetName(Pdo); > + > + Length = sizeof("devices/console/") + (ULONG)strlen(Name); > + > + Path = __FrontendAllocate(Length); > + > + status = STATUS_NO_MEMORY; > + if (Path == NULL) > + goto fail1; > + > + status = RtlStringCbPrintfA(Path, > + Length, > + "device/console/%s", > + Name); > + if (!NT_SUCCESS(status)) > + goto fail2; > + > + Frontend = __FrontendAllocate(sizeof(XENCONS_FRONTEND)); > + > + status = STATUS_NO_MEMORY; > + if (Frontend == NULL) > + goto fail3; > + > + Frontend->RefCount = 1; > + Frontend->Pdo = Pdo; > + Frontend->Path = Path; > + Frontend->BackendDomain = DOMID_INVALID; > + > + KeInitializeSpinLock(&Frontend->Lock); > + > + FdoGetDebugInterface(PdoGetFdo(Pdo), &Frontend->DebugInterface); > + FdoGetSuspendInterface(PdoGetFdo(Pdo), &Frontend- > >SuspendInterface); > + FdoGetStoreInterface(PdoGetFdo(Pdo), &Frontend->StoreInterface); > + > + // TODO: Initialize Ring > + > + KeInitializeEvent(&Frontend->EjectEvent, NotificationEvent, FALSE); > + > + status = ThreadCreate(FrontendEject, Frontend, &Frontend- > >EjectThread); > + if (!NT_SUCCESS(status)) > + goto fail5; > + > + *ConsoleAbi = FrontendAbiV1; > + ConsoleAbi->Context = (PXENCONS_CONSOLE_CONTEXT)Frontend; > + > + Trace("<====\n"); > + > + return STATUS_SUCCESS; > + > +fail5: > + Error("fail5\n"); > + > + RtlZeroMemory(&Frontend->EjectEvent, sizeof(KEVENT)); > + > + // TODO: Teardown Ring > + > +//fail4: > + Error("fail4\n"); > + > + RtlZeroMemory(&Frontend->StoreInterface, > + sizeof(XENBUS_STORE_INTERFACE)); > + > + RtlZeroMemory(&Frontend->SuspendInterface, > + sizeof(XENBUS_SUSPEND_INTERFACE)); > + > + RtlZeroMemory(&Frontend->DebugInterface, > + sizeof(XENBUS_DEBUG_INTERFACE)); > + > + Frontend->Online = FALSE; > + > + RtlZeroMemory(&Frontend->Lock, sizeof(KSPIN_LOCK)); > + > + Frontend->BackendDomain = 0; > + Frontend->Path = NULL; > + Frontend->Pdo = NULL; > + > + ASSERT(IsZeroMemory(Frontend, sizeof(XENCONS_FRONTEND))); > + > + __FrontendFree(Frontend); > + > +fail3: > + Error("fail3\n"); > + > +fail2: > + Error("fail2\n"); > + > + __FrontendFree(Path); > +fail1: > + Error("fail1 (%08x)\n", status); > + > + return status; > +} > + > diff --git a/src/xencons/frontend.h b/src/xencons/frontend.h > new file mode 100755 > index 0000000..289f36d > --- /dev/null > +++ b/src/xencons/frontend.h > @@ -0,0 +1,68 @@ > +/* Copyright (c) Citrix Systems Inc. > +* All rights reserved. > +* > +* Redistribution and use in source and binary forms, > +* with or without modification, are permitted provided > +* that the following conditions are met: > +* > +* * Redistributions of source code must retain the above > +* copyright notice, this list of conditions and the > +* following disclaimer. > +* * Redistributions in binary form must reproduce the above > +* copyright notice, this list of conditions and the > +* following disclaimer in the documentation and/or other > +* materials provided with the distribution. > +* > +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND > +* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, > +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF > +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE > +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR > +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, > +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, > +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR > +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS > +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, > +* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING > +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE > +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF > +* SUCH DAMAGE. > +*/ > + > +#ifndef _XENCONS_FRONTEND_H > +#define _XENCONS_FRONTEND_H > + > +#include <ntddk.h> > + > +#include "driver.h" > +#include "console_abi.h" > + > +typedef struct _XENCONS_FRONTEND XENCONS_FRONTEND, > *PXENCONS_FRONTEND; > + > +extern NTSTATUS > +FrontendCreate( > + IN PXENCONS_PDO Pdo, > + IN PXENCONS_CONSOLE_ABI ConsoleAbi > + ); > + > +extern PXENCONS_PDO > +FrontendGetPdo( > + IN PXENCONS_FRONTEND Frontend > + ); > + > +extern PCHAR > +FrontendGetPath( > + IN PXENCONS_FRONTEND Frontend > + ); > + > +extern PCHAR > +FrontendGetBackendPath( > + IN PXENCONS_FRONTEND Frontend > + ); > + > +extern USHORT > +FrontendGetBackendDomain( > + IN PXENCONS_FRONTEND Frontend > + ); > + > +#endif // _XENCONS_FRONTEND_H > diff --git a/src/xencons/pdo.c b/src/xencons/pdo.c > index 74be759..935b6ca 100755 > --- a/src/xencons/pdo.c > +++ b/src/xencons/pdo.c > @@ -46,6 +46,7 @@ > #include "pdo.h" > #include "console_abi.h" > #include "console.h" > +#include "frontend.h" > #include "thread.h" > #include "dbg_print.h" > #include "assert.h" > @@ -1945,7 +1946,7 @@ PdoCreate( > if (Device == NULL) > status = ConsoleCreate(Fdo, &Pdo->ConsoleAbi); > else > - status = STATUS_SUCCESS;// TODO: create frontend > + status = FrontendCreate(Pdo, &Pdo->ConsoleAbi); > if (!NT_SUCCESS(status)) > goto fail5; > > diff --git a/vs2015/xencons/xencons.vcxproj > b/vs2015/xencons/xencons.vcxproj > index 2e9d208..8846b8e 100644 > --- a/vs2015/xencons/xencons.vcxproj > +++ b/vs2015/xencons/xencons.vcxproj > @@ -70,6 +70,7 @@ > <ClCompile Include="../../src/xencons/registry.c" /> > <ClCompile Include="../../src/xencons/console.c" /> > <ClCompile Include="../../src/xencons/stream.c" /> > + <ClCompile Include="../../src/xencons/frontend.c" /> > <ClCompile Include="../../src/xencons/thread.c" /> > </ItemGroup> > <ItemGroup> > diff --git a/vs2017/xencons/xencons.vcxproj > b/vs2017/xencons/xencons.vcxproj > index 6c67fe8..9811da0 100644 > --- a/vs2017/xencons/xencons.vcxproj > +++ b/vs2017/xencons/xencons.vcxproj > @@ -78,6 +78,7 @@ > <ClCompile Include="../../src/xencons/registry.c" /> > <ClCompile Include="../../src/xencons/console.c" /> > <ClCompile Include="../../src/xencons/stream.c" /> > + <ClCompile Include="../../src/xencons/frontend.c" /> > <ClCompile Include="../../src/xencons/thread.c" /> > </ItemGroup> > <ItemGroup> > -- > 2.8.3 > > > _______________________________________________ > win-pv-devel mailing list > win-pv-devel@xxxxxxxxxxxxxxxxxxxx > https://lists.xenproject.org/mailman/listinfo/win-pv-devel _______________________________________________ win-pv-devel mailing list win-pv-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/win-pv-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |