From mboxrd@z Thu Jan 1 00:00:00 1970 From: Ian Campbell Subject: [PATCH 5 of 5] REBASE-4.1: xiu: add xenctrlosdep backend Date: Tue, 07 Dec 2010 14:33:04 +0000 Message-ID: <6fbe1c0939894dd12e2d.1291732384@zakaz.uk.xensource.com> References: Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-api-bounces-GuqFBffKawuULHF6PoxzQEEOCMrvLtNR@public.gmane.org Errors-To: xen-api-bounces-GuqFBffKawuULHF6PoxzQEEOCMrvLtNR@public.gmane.org To: xen-devel-GuqFBffKawuULHF6PoxzQEEOCMrvLtNR@public.gmane.org, xen-api-GuqFBffKawuULHF6PoxzQEEOCMrvLtNR@public.gmane.org Cc: Ian Campbell List-Id: xen-devel@lists.xenproject.org # HG changeset patch # User root-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org # Date 1291731939 18000 # Node ID 6fbe1c0939894dd12e2df5e930fbe9f60d24b3d8 # Parent 791652226f0e89265bf5ba50d0fe17c69a98dee7 REBASE-4.1: xiu: add xenctrlosdep backend. This interface was recently added to the upstream libxenctrl to allow interception of the calls to the hypervisor. Convert eventchn/eventchn_injection.c and xc/xc_lib_injection.c into an XIU backend for this interface. (depends on global rebase to Xen 4.1) Signed-off-by: Ian Campbell diff -r 791652226f0e -r 6fbe1c093989 Makefile.in --- a/Makefile.in Tue Dec 07 09:18:49 2010 -0500 +++ b/Makefile.in Tue Dec 07 09:25:39 2010 -0500 @@ -57,6 +57,7 @@ endif $(MAKE) -C cpuid $(MAKE) -C vhd $(MAKE) -C tapctl + $(MAKE) -C fake endif install: @@ -106,6 +107,7 @@ endif $(MAKE) -C cpuid install $(MAKE) -C vhd install $(MAKE) -C tapctl install + $(MAKE) -C fake install endif uninstall: @@ -155,6 +157,7 @@ endif $(MAKE) -C cpuid uninstall $(MAKE) -C vhd uninstall $(MAKE) -C tapctl uninstall + $(MAKE) -C fake uninstall endif bins: @@ -215,6 +218,7 @@ endif $(MAKE) -C cpuid doc $(MAKE) -C vhd doc $(MAKE) -C tapctl doc + $(MAKE) -C fake doc $(MAKE) -C xen-utils doc .PHONY: clean @@ -243,6 +247,7 @@ endif $(MAKE) -C xen-utils clean cleanxen: + $(MAKE) -C fake clean ifeq ($(WITH_XEN_SYSTEM_BINDINGS),0) $(MAKE) -C mmap clean endif diff -r 791652226f0e -r 6fbe1c093989 fake/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fake/Makefile Tue Dec 07 09:25:39 2010 -0500 @@ -0,0 +1,27 @@ +CC := gcc + +CFLAGS := -O1 +CFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls -fno-strict-aliasing -std=gnu99 +CFLAGS += -mno-tls-direct-seg-refs +CFLAGS += -Wall -Wstrict-prototypes -Wno-unused-value -Wdeclaration-after-statement -Werror -Wmissing-prototypes +CFLAGS += -D__XEN_TOOLS__ -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_GNU_SOURCE + +all: xenctrl_osdep_xiu.so + @: + +xeninterrcept_xiu.o: xenctrl_osdep_xiu.c + $(CC) $(CFLAGS) -c -o xenctrl_osdep_xiu.o xenctrl_osdep_xiu.c + +xenctrl_osdep_xiu.so: xenctrl_osdep_xiu.o + $(CC) $(CFLAGS) -shared -o xenctrl_osdep_xiu.so xenctrl_osdep_xiu.o -lxenctrl + +install: xenctrl_osdep_xiu.so + mkdir -p $$(DESTDIR)/opt/xensource/lib/xenctrl/ + cp xenctrl_osdep_xiu.so $(DESTDIR)/opt/xensource/lib/xenctrl/osdep_xiu.so + +clean: + rm -f xeninterrcept_xiu.o + rm -f xenctrl_osdep_xiu.so + +uninstall: + rm -f $(DESTDIR)/opt/xensource/lib/xenctrl/osdep_xiu.so diff -r 791652226f0e -r 6fbe1c093989 fake/xenctrl_osdep_xiu.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fake/xenctrl_osdep_xiu.c Tue Dec 07 09:25:39 2010 -0500 @@ -0,0 +1,609 @@ +/* + * Copyright (C) 2010 Citrix Systems Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; version 2.1 only. with the special + * exception on linking described in file LICENSE. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "marshall.h" + +#define IPRINTF(_x, _f, _a...) xc_osdep_log(_x,XTL_INFO,0, _f , ## _a) + +#define ERROR(_x, _m, _a...) xc_osdep_log(_x,XTL_ERROR,XC_INTERNAL_ERROR,_m , ## _a ) +#define PERROR(_x, _m, _a...) xc_osdep_log(_x,XTL_ERROR,XC_INTERNAL_ERROR,_m \ + " (%d = %s)", ## _a , errno, xc_strerror(xch, errno)) + +#define HYPCALLcmd "hypcall" + +static xc_osdep_handle xiu_privcmd_open(xc_interface *xch) +{ + struct sockaddr_un remote; + char *s; + int fd, len; + + s = getenv("XIU"); + if (!s) + { + ERROR(xch, "XIU not found. Set $XIU"); + return XC_OSDEP_OPEN_ERROR; + } + + snprintf(remote.sun_path, 256, "%s-xc", s); + remote.sun_family = AF_UNIX; + len = strlen(remote.sun_path) + sizeof(remote.sun_family); + + fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd == -1) + { + ERROR(xch, "XIU: Cannot open Unix domain socket"); + return XC_OSDEP_OPEN_ERROR; + } + + if (connect(fd, (struct sockaddr *)&remote, len) != 0) + { + ERROR(xch, "XIU: Cannot connect to Unix domain socket %s.", remote.sun_path); + return XC_OSDEP_OPEN_ERROR; + } + + return (xc_osdep_handle)fd; +} + +static int xiu_privcmd_close(xc_interface *xch, xc_osdep_handle h) +{ + int fd = (int)h; + return close(fd); +} + +#define DOMAINHANDLE "%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x" + +static int fake_xen_domctl(int fd, struct xen_domctl *domctl) +{ + #define DOMCTLcmd "domctl" + switch (domctl->cmd) { + case XEN_DOMCTL_pausedomain: + case XEN_DOMCTL_unpausedomain: + case XEN_DOMCTL_resumedomain: + case XEN_DOMCTL_destroydomain: + marshall_command(fd, "%s,%d,%d\n", DOMCTLcmd, domctl->cmd, domctl->domain); + return unmarshall_return(fd); + case XEN_DOMCTL_createdomain: /* W ssidref */ + marshall_command(fd, "%s,%d,%d,%d," DOMAINHANDLE "\n", DOMCTLcmd, + domctl->cmd, + (domctl->u.createdomain.flags|XEN_DOMCTL_CDF_hvm_guest)?1:0, + (domctl->u.createdomain.flags|XEN_DOMCTL_CDF_hap)?1:0, + domctl->u.createdomain.handle[0], + domctl->u.createdomain.handle[1], + domctl->u.createdomain.handle[2], + domctl->u.createdomain.handle[3], + domctl->u.createdomain.handle[4], + domctl->u.createdomain.handle[5], + domctl->u.createdomain.handle[6], + domctl->u.createdomain.handle[7], + domctl->u.createdomain.handle[8], + domctl->u.createdomain.handle[9], + domctl->u.createdomain.handle[10], + domctl->u.createdomain.handle[11], + domctl->u.createdomain.handle[12], + domctl->u.createdomain.handle[13], + domctl->u.createdomain.handle[14], + domctl->u.createdomain.handle[15]); + domctl->domain = unmarshall_int(fd); + return unmarshall_return(fd); + case XEN_DOMCTL_max_mem: /* W domid, maxmem */ + marshall_command(fd, "%s,%d,%d,%d\n", DOMCTLcmd, + domctl->cmd, + domctl->domain, domctl->u.max_mem.max_memkb); + return unmarshall_return(fd); + case XEN_DOMCTL_settimeoffset: /* W domid, time */ + marshall_command(fd, "%s,%d,%d,%d\n", DOMCTLcmd, + domctl->cmd, + domctl->domain, + domctl->u.settimeoffset.time_offset_seconds); + return unmarshall_return(fd); +#ifdef XEN_DOMCTL_setvmxassist + case XEN_DOMCTL_setvmxassist: /* W domid, use_vmxassist */ + marshall_command(fd, "%s,%d,%d,%d\n", DOMCTLcmd, + domctl->cmd, + domctl->domain, + domctl->u.setvmxassist.use_vmxassist); + return unmarshall_return(fd); +#endif + case XEN_DOMCTL_max_vcpus: /* W domid, max */ + marshall_command(fd, "%s,%d,%d,%d\n", DOMCTLcmd, + domctl->cmd, + domctl->domain, + domctl->u.max_vcpus.max); + return unmarshall_return(fd); + case XEN_DOMCTL_setdomainhandle: { /* domid, fd */ + marshall_command(fd, "%s,%d,%d," DOMAINHANDLE "\n", DOMCTLcmd, + domctl->cmd, + domctl->domain, + domctl->u.setdomainhandle.handle[0], + domctl->u.setdomainhandle.handle[1], + domctl->u.setdomainhandle.handle[2], + domctl->u.setdomainhandle.handle[3], + domctl->u.setdomainhandle.handle[4], + domctl->u.setdomainhandle.handle[5], + domctl->u.setdomainhandle.handle[6], + domctl->u.setdomainhandle.handle[7], + domctl->u.setdomainhandle.handle[8], + domctl->u.setdomainhandle.handle[9], + domctl->u.setdomainhandle.handle[10], + domctl->u.setdomainhandle.handle[11], + domctl->u.setdomainhandle.handle[12], + domctl->u.setdomainhandle.handle[13], + domctl->u.setdomainhandle.handle[14], + domctl->u.setdomainhandle.handle[15]); + return unmarshall_return(fd); + } + /* just returning success : might need init */ + case XEN_DOMCTL_getvcpucontext: + case XEN_DOMCTL_getvcpuaffinity: + return 0; + /* just returning success */ + case XEN_DOMCTL_scheduler_op: + return 0; + case XEN_DOMCTL_shadow_op: + /* Only fd set/get allocation at the moment */ + marshall_command(fd, "%s,%d,%d,%d,%d,%d\n", DOMCTLcmd, + domctl->cmd, + domctl->domain, + domctl->u.shadow_op.op, + domctl->u.shadow_op.mode, + domctl->u.shadow_op.mb); + if(domctl->u.shadow_op.op == XEN_DOMCTL_SHADOW_OP_GET_ALLOCATION) + domctl->u.shadow_op.mb = unmarshall_int(fd); + + return unmarshall_return(fd); + + /* just return success */ + case XEN_DOMCTL_ioport_permission: + case XEN_DOMCTL_irq_permission: + case XEN_DOMCTL_iomem_permission: + case XEN_DOMCTL_setvcpuaffinity: + case XEN_DOMCTL_setvcpucontext: + case XEN_DOMCTL_getmemlist: + case XEN_DOMCTL_getvcpuinfo: +#ifdef XEN_DOMCTL_get_runstate_info + case XEN_DOMCTL_get_runstate_info: +#endif + case XEN_DOMCTL_set_machine_address_size: +#ifdef XEN_DOMCTL_suppress_spurious_page_faults + case XEN_DOMCTL_suppress_spurious_page_faults: +#endif + return 0; + default: + return -EINVAL; + } +} + +static int fake_xen_sysctl(int fd, struct xen_sysctl *sysctl) +{ + #define SYSCTLcmd "sysctl" + switch (sysctl->cmd) { + case XEN_SYSCTL_getdomaininfolist: { + xc_domaininfo_t *info; int num, i; + + get_xen_guest_handle(info, sysctl->u.getdomaininfolist.buffer); + + marshall_command(fd, "%s,%d,%d,%d\n", SYSCTLcmd, sysctl->cmd, + sysctl->u.getdomaininfolist.first_domain, + sysctl->u.getdomaininfolist.max_domains); + num = unmarshall_int(fd); + for (i = 0; i < num; i++) { + int uuid[16], j, flags; + char **ret; + + ret = unmarshall_multiple(fd); + if (!ret) + return -EBADF; + + /* domid,uuid,flags */ + info->domain = atoi(ret[0]); + + parse_uuid(ret[1], uuid); + for (j = 0; j < 16; j++) + info->handle[j] = uuid[j] & 0xff; + + flags = atoi(ret[2]); + info->flags = 0; + if (flags & 0x1) info->flags |= XEN_DOMINF_dying; + if (flags & 0x2) info->flags |= XEN_DOMINF_shutdown; + if (flags & 0x4) info->flags |= XEN_DOMINF_paused; + if (flags & 0x8) info->flags |= XEN_DOMINF_blocked; + if (flags & 0x10) info->flags |= XEN_DOMINF_running; + if (flags & 0x20) info->flags |= XEN_DOMINF_hvm_guest; + info->flags |= ((flags >> 8) & 0xff) << XEN_DOMINF_shutdownshift; + + info->nr_online_vcpus = atoi(ret[3]); + info->max_vcpu_id = atoi(ret[4]); + + info->tot_pages = atoi(ret[5]); + info->max_pages = atoi(ret[6]); + info->shared_info_frame = atoi(ret[7]); + info->cpu_time = atoi(ret[8]); + info->ssidref = atoi(ret[9]); + + string_split_free(ret); + info++; + + } + sysctl->u.getdomaininfolist.num_domains = num; + return unmarshall_return(fd); + } + case XEN_SYSCTL_readconsole: + case XEN_SYSCTL_debug_keys: + return 0; + case XEN_SYSCTL_physinfo: { + char **ret; + int sockets_per_node; + + marshall_command(fd, "%s,%d\n", SYSCTLcmd, sysctl->cmd); + ret = unmarshall_multiple(fd); + if (!ret) return -EBADF; + + sockets_per_node = atoi(ret[2]); + + sysctl->u.physinfo.threads_per_core = atoi(ret[0]); + sysctl->u.physinfo.cores_per_socket = atoi(ret[1]); +#if XEN_SYSCTL_INTERFACE_VERSION < 6 + sysctl->u.physinfo.sockets_per_node = sockets_per_node; +#endif + sysctl->u.physinfo.nr_nodes = atoi(ret[3]); +#if XEN_SYSCTL_INTERFACE_VERSION >= 6 + sysctl->u.physinfo.nr_cpus = + sysctl->u.physinfo.threads_per_core * + sysctl->u.physinfo.cores_per_socket * + sockets_per_node * + sysctl->u.physinfo.nr_nodes; +#endif + sysctl->u.physinfo.cpu_khz = atoi(ret[4]); + sysctl->u.physinfo.total_pages = atoi(ret[5]); + sysctl->u.physinfo.free_pages = atoi(ret[6]); + sysctl->u.physinfo.scrub_pages = 0; + + string_split_free(ret); + return unmarshall_return(fd); + } + case XEN_SYSCTL_getcpuinfo: { + xen_sysctl_cpuinfo_t *info; + int num, i; + + get_xen_guest_handle(info, sysctl->u.getcpuinfo.info); + marshall_command(fd, "%s,%d,%d\n", SYSCTLcmd, sysctl->cmd, sysctl->u.getcpuinfo.max_cpus); + num = unmarshall_int(fd); + for (i = 0; i < num; i++) { + info[i].idletime = unmarshall_int64(fd); + } + return unmarshall_return(fd); + } + case XEN_SYSCTL_sched_id: + return 0; + default: + return -EINVAL; + } + return 0; +} + +static int fake_xen_eventchn(int fd, unsigned long cmd, unsigned long arg) +{ + switch (cmd) { + case EVTCHNOP_alloc_unbound: + case EVTCHNOP_reset: + return 0; + default: + return -EINVAL; + } + return 0; +} + +static int fake_xen_memoryop(int fd, unsigned long cmd, struct xen_memory_reservation *reservation) +{ + switch (cmd) { + case XENMEM_set_memory_map: + case XENMEM_increase_reservation: + case XENMEM_decrease_reservation: + case XENMEM_populate_physmap: + return 0; + default: + return -EINVAL; + } + return 0; +} + +static int fake_xen_hvmop(int fd, unsigned long cmd, unsigned long arg) +{ + switch (cmd) { + case HVMOP_get_param: + return 0; + default: + return -EINVAL; + } + return 0; +} + +static int fake_xen_schedop(int fd, unsigned long cmd, sched_remote_shutdown_t *arg) +{ + switch (cmd) { + case SCHEDOP_remote_shutdown: + marshall_command(fd, "%s,%d,%d,%d\n", HYPCALLcmd, + 1, + arg->domain_id, + arg->reason); + return unmarshall_return(fd); + default: + return -EINVAL; + } + return 0; +} + +static int fake_xen_versionop(int fd, unsigned long cmd, void * arg) +{ + switch (cmd) { + case XENVER_extraversion: + memset(arg, '\0', sizeof(xen_extraversion_t)); + memcpy(arg, ".0", 2); + return 0; + case XENVER_compile_info: + memset(arg, '\0', sizeof(xen_compile_info_t)); + return 0; + case XENVER_capabilities: + memset(arg, '\0', sizeof(xen_capabilities_info_t)); + #define CAPA "xen-3.0-x86_64 xen-3.0-x86_32p hvm-3.0-x86_32 hvm-3.0-x86_32p hvm-3.0-x86_64" + memcpy(arg, CAPA, strlen(CAPA)); + #undef CAPA + return 0; + case XENVER_changeset: + memset(arg, '\0', sizeof(xen_changeset_info_t)); + return 0; + case XENVER_platform_parameters: + memset(arg, '\0', sizeof(xen_platform_parameters_t)); + return 0; + case XENVER_version: + return (((3 << 16) & 0xffff0000) + (1 & 0xffff)); /* 3.1 */ + default: + return -EINVAL; + } + return 0; +} + +static int xiu_privcmd_hypercall(xc_interface *xch, xc_osdep_handle h, privcmd_hypercall_t *hypercall) +{ + int fd = (int)h; + if (!hypercall) return -EINVAL; + switch (hypercall->op) { + case __HYPERVISOR_domctl: + return fake_xen_domctl(fd, (struct xen_domctl *) (intptr_t)hypercall->arg[0]); + case __HYPERVISOR_sysctl: + return fake_xen_sysctl(fd, (struct xen_sysctl *) (intptr_t)hypercall->arg[0]); + case __HYPERVISOR_event_channel_op: + return fake_xen_eventchn(fd, hypercall->arg[0], hypercall->arg[1]); + case __HYPERVISOR_memory_op: + return fake_xen_memoryop(fd, hypercall->arg[0], (struct xen_memory_reservation *) (intptr_t)hypercall->arg[2]); + case __HYPERVISOR_hvm_op: + return fake_xen_hvmop(fd, hypercall->arg[0], hypercall->arg[2]); + case __HYPERVISOR_sched_op: + return fake_xen_schedop(fd, hypercall->arg[0], (sched_remote_shutdown_t *) (intptr_t)hypercall->arg[1]); + case __HYPERVISOR_xen_version: + return fake_xen_versionop(fd, hypercall->arg[0], (void *) (intptr_t)hypercall->arg[1]); + default: + return -EINVAL; + } +} + +static void *xiu_privcmd_map_foreign_batch(xc_interface *xch, xc_osdep_handle h, uint32_t dom, int prot, + xen_pfn_t *arr, int num) +{ + return mmap(NULL, num << XC_PAGE_SHIFT, prot, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); +} + +static void *xiu_privcmd_map_foreign_bulk(xc_interface *xch, xc_osdep_handle h, uint32_t dom, int prot, + const xen_pfn_t *arr, int *err, unsigned int num) +{ + return mmap(NULL, (unsigned long)num << XC_PAGE_SHIFT, prot, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); +} + +static void *xiu_privcmd_map_foreign_range(xc_interface *xch, xc_osdep_handle h, uint32_t dom, int size, int prot, + unsigned long mfn) +{ + int num = (size + XC_PAGE_SIZE - 1) >> XC_PAGE_SHIFT; + return mmap(NULL, num, prot, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); +} + +static void *xiu_privcmd_map_foreign_ranges(xc_interface *xch, xc_osdep_handle h, uint32_t dom, size_t size, int prot, + size_t chunksize, privcmd_mmap_entry_t entries[], + int nentries) +{ + int num_per_entry; + int num; + + num_per_entry = chunksize >> XC_PAGE_SHIFT; + num = num_per_entry * nentries; + return mmap(NULL, num, prot, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); +} + +static struct xc_osdep_ops xiu_privcmd_ops = +{ + .open = &xiu_privcmd_open, + .close = &xiu_privcmd_close, + .u.privcmd = { + .hypercall = &xiu_privcmd_hypercall, + + .map_foreign_batch = &xiu_privcmd_map_foreign_batch, + .map_foreign_bulk = &xiu_privcmd_map_foreign_bulk, + .map_foreign_range = &xiu_privcmd_map_foreign_range, + .map_foreign_ranges = &xiu_privcmd_map_foreign_ranges, + } +}; + +static xc_osdep_handle xiu_evtchn_open(xc_evtchn *xce) +{ + struct sockaddr_un remote; + char *s; + int fd, len; + + s = getenv("XIU"); + if (!s) + { + ERROR(xce, "XIU not found. Set $XIU"); + return XC_OSDEP_OPEN_ERROR; + } + snprintf(remote.sun_path, 256, "%s-ev", s); + remote.sun_family = AF_UNIX; + len = strlen(remote.sun_path) + sizeof(remote.sun_family); + + fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd == -1) + { + ERROR(xce, "XIU: Cannot open Unix domain socket"); + return XC_OSDEP_OPEN_ERROR; + } + + if (connect(fd, (struct sockaddr *)&remote, len) != 0) + { + ERROR(xce, "XIU: Cannot connect to Unix domain socket %s.", remote.sun_path); + return XC_OSDEP_OPEN_ERROR; + } + + return (xc_osdep_handle)fd; +} + +static int xiu_evtchn_close(xc_evtchn *xce, xc_osdep_handle h) +{ + int fd = (int)h; + return close(fd); +} + +static int xiu_evtchn_fd(xc_evtchn *xce, xc_osdep_handle h) +{ + return (int)h; +} + +static int xiu_evtchn_notify(xc_evtchn *xce, xc_osdep_handle h, evtchn_port_t port) +{ + int fd = (int)h; + marshall_command(fd, "ioctl,notify,%d\n", port); + return unmarshall_return(fd); +} + +static evtchn_port_or_error_t +xiu_evtchn_bind_unbound_port(xc_evtchn *xce, xc_osdep_handle h, int domid) +{ + return -EINVAL; +} + +static evtchn_port_or_error_t +xiu_evtchn_bind_interdomain(xc_evtchn *xce, xc_osdep_handle h, int domid, + evtchn_port_t remote_port) +{ + int fd = (int)h; + marshall_command(fd, "ioctl,bind_interdomain,%d,%d\n", domid, remote_port); + return unmarshall_return(fd); +} + +static evtchn_port_or_error_t +xiu_evtchn_bind_virq(xc_evtchn *xce, xc_osdep_handle h, unsigned int virq) +{ + int fd = (int)h; + marshall_command(fd, "ioctl,bind_virq,%d\n", virq); + return unmarshall_return(fd); +} + +static int xiu_evtchn_unbind(xc_evtchn *xce, xc_osdep_handle h, evtchn_port_t port) +{ + int fd = (int)h; + marshall_command(fd, "ioctl,unbind,%d\n", port); + return unmarshall_return(fd); +} + +static evtchn_port_or_error_t xiu_evtchn_pending(xc_evtchn *xce, xc_osdep_handle h) +{ + int fd = (int)h; + evtchn_port_t port; + + marshall_command(fd, "read\n"); + port = unmarshall_int(fd); + if (unmarshall_return(fd) < 0) + return port; + else + return -1; +} + +static int xiu_evtchn_unmask(xc_evtchn *xce, xc_osdep_handle h, evtchn_port_t port) +{ + int fd = (int)h; + marshall_command(fd, "write,%d\n", port); + return unmarshall_return(fd); +} + +static struct xc_osdep_ops xiu_evtchn_ops = { + .open = &xiu_evtchn_open, + .close = &xiu_evtchn_close, + + .u.evtchn = { + .fd = &xiu_evtchn_fd, + .notify = &xiu_evtchn_notify, + .bind_unbound_port = &xiu_evtchn_bind_unbound_port, + .bind_interdomain = &xiu_evtchn_bind_interdomain, + .bind_virq = &xiu_evtchn_bind_virq, + .unbind = &xiu_evtchn_unbind, + .pending = &xiu_evtchn_pending, + .unmask = &xiu_evtchn_unmask, + }, +}; + +static struct xc_osdep_ops * xiu_osdep_init(xc_interface *xch, enum xc_osdep_type type) +{ + if (getenv("XIU") == NULL) + { + ERROR(xch, "XIU not found. Set $XIU"); + return NULL; + } + + switch ( type ) + { + case XC_OSDEP_PRIVCMD: + return &xiu_privcmd_ops; + case XC_OSDEP_EVTCHN: + return &xiu_evtchn_ops; + case XC_OSDEP_GNTTAB: + ERROR(xch, "GNTTAB interface not supported on this platform"); + return NULL; + default: + return NULL; + } +} + +xc_osdep_info_t xc_osdep_info = { + .name = "Xen In Userspace (XIU) Simulator", + .init = &xiu_osdep_init, + .fake = 1, +}; + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */