xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries
@ 2015-07-15 15:46 Ian Campbell
  2015-07-15 15:46 ` [PATCH XEN v2 01/15] docs: Partial toolstack library API/ABI stabilisation Ian Campbell
                   ` (27 more replies)
  0 siblings, 28 replies; 55+ messages in thread
From: Ian Campbell @ 2015-07-15 15:46 UTC (permalink / raw)
  To: xen-devel
  Cc: minios-devel, Wei Liu, Stefano Stabellini, Ian Jackson, Roger Pau Monne

(this is clearly not 4.6 material, aiming for 4.7)

In <1431963008.4944.80.camel@citrix.com> I proposed stabilising some
parts of the libxenctrl API/ABI by disaggregating into separate
libraries.

After the previous proof of concept I have now split out:
      * xentoollog
      * evtch
      * gntdev and gntshr
      * hypercalls
      * privileged foreign memory mappings

These represent the core low level functionality which everything else
needs, I think, and so are moving things down into a layer below libxc
(i.e. libxc uses all of these).

There are 3 series, against xen.git (15 patches), mini-os.git (5
patches) and qemu-xen-trad.git (5 patches). The patches against xen.git
point to the patches in the other two trees via instructions to update
the relevant Config.mk field. The perils of changing unstable
interfaces!

NB: minios-devel will only get the mini-os side.

The code in for all three can be found in:
git://xenbits.xen.org/people/ianc/xen.git               libxenctrl-split-v2
git://xenbits.xen.org/people/ianc/qemu-xen-unstable.git libxenctrl-split-v2
git://xenbits.xen.org/people/ianc/mini-os.git           libxenctrl-split-v2

The tip of the xen.git branch contains an extra patch adding a .config
into the tree which should get the correct things for the HEAD of the
branch, but not further back.

Still to come would be libraries for specific out of tree purposes
(device model, kexec), which would be adding new library at the same
level as libxc I think, rather than underneath, i.e. also using the
libraries split out here, but hopefully not libxenctrl itself.

The new libraries use linker version-scripts to hopefully make future
ABI changes be possible in a compatible way.

I'm stilling mulling over putting everything into tools/libs/FOO
instead of tools/libxenFOO, I still haven't but I could if people think
it is worthwhile. Eventually I'd like to split libxc into libxenguest
and libxenctrl to cut down on the amount of strange cross talk...

I've now completely removed the osdep layer.

The whole thing has been build and runtime tested on Linux and stubdoms,
and built (but not run) on FreeBSD. Neither NetBSD nor Solaris have been
tested at all. It's certainly not impossible that I've not got the
#includes in the new files quite right.

The original proposal has morphed into
docs/misc/toolstack-library-abis.pandoc here, and I've been trying to
update in the patches which touch things, which is useful for book
keeping as this work progresses.

However I'm not sure it serves a useful long term purpose (certainly not
with the level of detail of the per-library function names). I shall
likely keep it around for a few iterations but I think eventually I'll
strip it out or replace it with something more suitable for long term
documentation.


Ian

^ permalink raw reply	[flat|nested] 55+ messages in thread

* [PATCH XEN v2 01/15] docs: Partial toolstack library API/ABI stabilisation
  2015-07-15 15:46 [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries Ian Campbell
@ 2015-07-15 15:46 ` Ian Campbell
  2015-07-15 15:46 ` [PATCH XEN v2 02/15] tools/Rules.mk: Properly handle libraries with recursive dependcies Ian Campbell
                   ` (26 subsequent siblings)
  27 siblings, 0 replies; 55+ messages in thread
From: Ian Campbell @ 2015-07-15 15:46 UTC (permalink / raw)
  To: ian.jackson, wei.liu2, xen-devel
  Cc: roger.pau, Ian Campbell, stefano.stabellini

---
DraftB:
  - Feedback from Jan and Andy
  - QEMU usage by functional area
  - Annotated with what things are and users
  - Renamed to docs/misc/toolstack-library-abis.pandoc
  - Change method for gathering symbols to omit static/non-exported
    stuff.
  - Some additional functional classification, and start to annotate
    the underlying interfaces plus known users.
---
 docs/Makefile                           |   2 +-
 docs/misc/toolstack-library-abis.pandoc | 849 ++++++++++++++++++++++++++++++++
 2 files changed, 850 insertions(+), 1 deletion(-)
 create mode 100644 docs/misc/toolstack-library-abis.pandoc

diff --git a/docs/Makefile b/docs/Makefile
index 272292c..79a17f4 100644
--- a/docs/Makefile
+++ b/docs/Makefile
@@ -16,7 +16,7 @@ MARKDOWNSRC-y := $(sort $(shell find misc -name '*.markdown' -print))
 
 TXTSRC-y := $(sort $(shell find misc -name '*.txt' -print))
 
-PANDOCSRC-y := $(sort $(shell find specs -name '*.pandoc' -print))
+PANDOCSRC-y := $(sort $(shell find misc specs -name '*.pandoc' -print))
 
 # Documentation targets
 DOC_MAN1 := $(patsubst man/%.pod.1,man1/%.1,$(MAN1SRC-y))
diff --git a/docs/misc/toolstack-library-abis.pandoc b/docs/misc/toolstack-library-abis.pandoc
new file mode 100644
index 0000000..c24be81
--- /dev/null
+++ b/docs/misc/toolstack-library-abis.pandoc
@@ -0,0 +1,849 @@
+% Xen toolstack library API/ABIs
+% Ian Campbell <ian.campbell@citrix.com>
+% Draft B
+
+# Introduction
+
+The low-level `libxenctrl` library currently has an unstable API and
+ABI and some of the hypervisor interfaces which it exposes are
+similarly unstable.
+
+However several external projects use some of these interfaces (at
+least: qemu and kexec-tools), which presents problems for distros and
+other consumers. In particular the need for spurious rebuilds of those
+components against newer versions of Xen and difficulty supporting
+parallel installation of different versions of Xen (useful during
+upgrade).
+
+This document considers whether parts of `libxenctrl` can be split out
+into new libraries with more useful API and ABI guarantees.
+
+# ABI/API Compatibility Classes
+
+Compatibility opportunities:
+
+* `LAPI` -- Library API
+* `LABI` -- Library ABI
+* `HABI` -- Hypervisor ABI (includes ioctls).
+
+Each can either be Stable (`S`), Unstable (`U`) or don't care (`x`,
+because made moot by higher level interface class, e.g. no real point
+from an application PoV to a Stable HABI behind a unstable LABI).
+
+Stable vs. Unstable is across major hypervisor version bump, always
+aim to be stable across point releases.
+
+For libraries Stable means `SONAME` major component, but forward
+compatible only (i.e. old app on new library works, new app on old
+library may not link due to e.g. new symbols. This is the normal
+SONAME expectation). XXX find a link to the sort of scheme I mean.
+
+`HABI` may include ioctls used to access those ABIs, typically these
+are already required to be stable by the relevant OS maintainers.
+
+A library interface may fall into one of these categories (I expect
+there are others and we may not want any library to use some of even
+these):
+
+* Unstable `LAPI` (`Uxx`)
+    * The Wild West
+    * Current Examples: `libxenctrl`
+
+* Stable `LAPI`, Unstable `LABI` (`SUx`)
+    * Requires application rebuild for a new Xen version, but not
+      application source code changes.
+    * Current Examples: `libxenlight`
+
+* Stable `LAPI`, Stable `LABI`, Unstable `HABI` (`SSU`)
+    * Library can be switched out via dynamic linking across
+      hypervisor upgrade (mechanism TBD, pos. distro specific, e.g.
+      symlink switched on boot). Requires application/daemon restart
+      but not rebuild (but changing hypervisor version involves a
+      reboot anyway).
+    * Current Examples: None??
+
+* Stable `LAPI`, Stable `LABI`, Stable `HABI` (`SSS`)
+    * Applications linked again a library will function against any
+      hypervisor version.
+    * Current Examples: None??
+
+# Goal
+
+Provide `SSU` or `SSS` interfaces for major external consumers of
+current libxenctrl functionality.
+
+Out of scope (for now): `SSU` or `SSS` interfaces for consumers of
+`libxenlight`. Rationale: Lets focus on fixing external consumers of
+libxenctrl first.
+
+# Known External Consumers of `libxenctrl`
+
+* qemu
+* kexec tools
+* in guest tools e.g. users of `libxenstore`, `libvchan`, and by
+  extension `grant table` and `event channel` functionality. NB:
+  `libxenstore` is already `SSU` or `SSS` (XXX?)
+
+# `libxenguest`
+
+Uses some of the same sources as `libxenctrl`. Could do with some
+rationalisation of what lives where.
+
+Not a candidate for API/ABI stability at this point.
+
+# Unstable libraries
+
+These libraries do not provide a stable interface and are required to
+be updated in lockstep with the hypervisor.
+
+## `libxenctrl`
+
+Gathered by:
+
+    $ objdump -T tools/libxc/libxenctrl.so| awk '$4 ~ /\.text/ { print $7 }' | sort -u
+
+The following proposes some functional groupings via some proposed
+split library names. In some cases we may also wish to consider
+replacing an API with one which can be properly maintained going
+forwards. e.g.:
+
+- perhaps replacing domctl's used by qemu with new stable
+  hypercall ABIs and reflecting that in new library APIs.
+- perhaps exposing more constrained versions of some broad interfaces
+  for external users.
+
+In addition to these there are many inlines in `xenctrl.h`. Where
+possible these should become either private functions or regular
+functions exported by the library.
+
+Notes:
+
+* Things marked "private" are generally defined in `xc_private.h` or
+  are otherwise supposedly internal but leaked.
+* Things marked "external, via ..." are generally expected to be used
+  via `...` (often a macro).
+* There are lots of static functions in the `xc_*` namespace.
+
+### Logging
+
+The following are already logically somewhat separate. They do not
+depend on any underlying Xen functionality.
+
+Interface                     Known external users
+----------------------------- --------------------
+`xtl_createlogger_stdiostream`
+`xtl_level_to_string`
+`xtl_log`
+`xtl_logger_destroy`
+`xtl_logv`
+`xtl_progress`
+`xtl_stdiostream_adjust_flags`
+`xtl_stdiostream_set_minlevel`
+
+### Basic interface
+
+    - xc_interface_close
+    - xc_interface_is_fake
+    - xc_interface_open
+
+### Event channels
+
+Interacting with Event Channels via `__HYPERVISOR_event_channel_op`
+(`EVTCHNOP_*`) or `/dev/xen/evtchn`.
+
+Interface                     Underlying interface             Known external users
+----------------------------- -------------------------------- --------------------
+`xc_evtchn_bind_interdomain`  `IOCTL_EVTCHN_BIND_INTERDOMAIN`  qemu-pv
+`xc_evtchn_bind_unbound_port` `IOCTL_EVTCHN_BIND_UNBOUND_PORT`
+`xc_evtchn_bind_virq`         `IOCTL_EVTCHN_BIND_VIRQ`
+`xc_evtchn_close`             `close(2)`                       qemu-dm
+`xc_evtchn_fd`
+`xc_evtchn_notify`            `IOCTL_EVTCHN_NOTIFY`            qemu-dm, qemu-pv
+`xc_evtchn_open`              `open(2)`                        qemu-dm, qemu-pv
+`xc_evtchn_pending`           `read(2)`                        qemu-dm, qemu-pv
+`xc_evtchn_unbind`            `IOCTL_EVTCHN_UNBIND`            qemu-pv
+`xc_evtchn_unmask`            `write(2)`                       qemu-dm, qemu-pv
+`xc_evtchn_alloc_unbound`     `EVTCHNOP_alloc_unbound`
+`xc_evtchn_reset`             `EVTCHNOP_reset`
+`xc_evtchn_status`            `EVTCHNOP_status`
+
+### Grant tables
+
+Interacting with Grant Tables via `__HYPERVISOR_grant_table_op`
+(`GNTTABOP_*`) or `/dev/xen/gnt{shr,alloc}`.
+
+Interface                         Underlying interface           Known external users
+--------------------------------- ------------------------------ --------------------
+`xc_gnttab_map_domain_grant_refs` `IOCTL_GNTDEV_SET_MAX_GRANTS`
+`xc_gnttab_map_grant_ref_notify`  `IOCTL_GNTDEV_MAP_GRANT_REF`
+`xc_gnttab_map_grant_ref`         `IOCTL_GNTDEV_MAP_GRANT_REF`   qemu-pv
+`xc_gnttab_map_grant_refs`        `IOCTL_GNTDEV_SET_MAX_GRANTS`  qemu-pv
+`xc_gnttab_munmap`                `munmap(2)`                    qemu-pv
+`xc_gnttab_open`                  `open(2)`                      qemu-pv
+`xc_gnttab_close`                 `close(2)`                     qemu-pv
+`xc_gnttab_set_max_grants`        `IOCTL_GNTDEV_SET_MAX_GRANTS`
+`xc_gntshr_close`                 `close(2)`
+`xc_gntshr_munmap`                `munmap(2)`
+`xc_gntshr_open`                  `open(2)`
+`xc_gntshr_share_page_notify`     `IOCTL_GNTALLOC_ALLOC_GREF`
+`xc_gntshr_share_pages`           `IOCTL_GNTALLOC_ALLOC_GREF`
+`xc_gnttab_op`                    `__HYPERVISOR_grant_table_op`
+`xc_gnttab_get_version`           `GNTTABOP_get_version`
+`xc_gnttab_map_table_v1`          `GNTTABOP_setup_table`
+`xc_gnttab_map_table_v2`          `GNTTABOP_setup_table`
+
+`xc_*_notify` also use `IOCTL_GNTALLOC_SET_UNMAP_NOTIFY`,
+`IOCTL_GNTALLOC_SET_UNMAP_NOTIFY`, etc
+
+### Hypercalls
+
+#### Making hypercalls
+
+Interface                         Underlying interface           Known external users
+--------------------------------- ------------------------------ --------------------
+`do_xen_hypercall`                `IOCTL_PRIVCMD_HYPERCALL`      private
+
+#### Wrappers
+
+Interface                         Known in-tree users           Known external users
+--------------------------------- ----------------------------- --------------------
+`do_memory_op`                    private                       private
+`xc_domctl`                       Save/Restore                  None
+`xc_sysctl`                       xencov, xenmon                None
+
+#### Hypercall buffers
+
+Allocate and manange (and attempt to enforce the use of) memory
+suitable for passing to a hypercall as a GUEST_HANDLE argument.
+
+Interface                           Known in-tree users       Known external users
+----------------------------------- ------------------------- --------------------
+`xc_hypercall_buffer_array_create`                            kexec-tools
+`xc_hypercall_buffer_array_destroy`                           kexec-tools
+
+The following are external via a corresponding `xc_` function:
+
+Interface                           Known in-tree users          Known external users
+----------------------------------- ---------------------------- --------------------
+`xc__hypercall_buffer_alloc`        xencov, xenlockprof, xenperf
+`xc__hypercall_buffer_alloc_pages`
+`xc__hypercall_buffer_array_alloc`                               kexec-tools
+`xc__hypercall_buffer_array_get`
+`xc__hypercall_buffer_free`         xencov, xenlockprof, xenperf
+`xc__hypercall_buffer_free_pages`
+
+The following are private:
+
+- `xc__hypercall_bounce_post`
+- `xc__hypercall_bounce_pre`
+- `xc__hypercall_buffer_cache_release`
+
+### Mapping foreign memory
+
+Interface                         Underlying interface           Known external users
+--------------------------------- ------------------------------ --------------------
+`xc_map_foreign_pages`            `IOCTL_PRIVCMD_MMAP...`        qemu-pv
+`xc_map_foreign_range`            `IOCTL_PRIVCMD_MMAP...`        qemu-dm, and qemu-pv
+`xc_map_foreign_ranges`
+`xc_map_foreign_batch`
+`xc_map_foreign_bulk`             `IOCTL_PRIVCMD_MMAPBATCH_V2`   qemu-dm
+`xc_map_foreign_bulk_compat`                                     private
+
+`xc_map_foreign_bulk_compat` is a stub for all not yet converted OSes
+and is used by netbsd & solaris.
+
+### Managing guest memory map
+
+Interface                          Underlying interface           Known external users
+---------------------------------  ------------------------------ --------------------
+`xc_domain_add_to_physmap`         `XENMEM_add_to_physmap`        qemu-dm
+`xc_domain_populate_physmap`       `XENMEM_populate_physmap`
+`xc_domain_populate_physmap_exact` `XENMEM_populate_physmap`      qemu-dm
+
+### Kexec
+
+Functions specifically for use by kexec tools
+
+Interface                     Underlying interface
+----------------------------- ------------------------------
+`xc_kexec_exec`               `KEXEC_CMD_kexec`
+`xc_kexec_get_range`          `KEXEC_CMD_kexec_get_range`
+`xc_kexec_load`               `KEXEC_CMD_kexec_unload`
+`xc_kexec_unload`             `KEXEC_CMD_kexec_unload`
+
+### Unclassified remains
+
+_Note_: Not everything which belongs in one of the above categorisations has
+        actually been moved to a suitable home.
+
+Symbols:
+
+    - bitmap_64_to_byte
+    - bitmap_byte_to_64
+    - discard_file_cache
+    - read_exact
+    - write_exact
+    - writev_exact
+    - xc_add_mmu_update
+    - xc_alloc_mmu_updates
+    - xc_assign_device
+    - xc_assign_dt_device
+    - xc_availheap
+    - xc_clear_domain_pages
+    - xc_clear_last_error
+    - xc_copy_to_domain_page
+    - xc_core_arch_auto_translated_physmap
+    - xc_core_arch_get_scratch_gpfn
+    - xc_core_arch_gpfn_may_present
+    - xc_core_arch_map_p2m
+    - xc_core_arch_map_p2m_writable
+    - xc_core_arch_memory_map_get
+    - xc_core_shdr_get
+    - xc_core_shdr_set
+    - xc_cpumap_alloc
+    - xc_cpumap_clearcpu
+    - xc_cpumap_setcpu
+    - xc_cpumap_testcpu
+    - xc_cpu_offline
+    - xc_cpu_online
+    - xc_cpupool_addcpu
+    - xc_cpupool_create
+    - xc_cpupool_destroy
+    - xc_cpupool_freeinfo
+    - xc_cpupool_getinfo
+    - xc_cpupool_infofree
+    - xc_cpupool_movedomain
+    - xc_cpupool_removecpu
+    - xc_cputopoinfo
+    - xc_deassign_device
+    - xc_deassign_dt_device
+    - xc_disable_turbo
+    - xc_domain_bind_pt_irq
+    - xc_domain_bind_pt_isa_irq
+    - xc_domain_bind_pt_pci_irq
+    - xc_domain_bind_pt_spi_irq
+    - xc_domain_cacheflush
+    - xc_domain_claim_pages
+    - xc_domain_create
+    - xc_domain_create_config
+    - xc_domain_debug_control
+    - xc_domain_decrease_reservation
+    - xc_domain_decrease_reservation_exact
+    - xc_domain_destroy
+    - xc_domain_disable_migrate
+    - xc_domain_dumpcore
+    - xc_domain_dumpcore_via_callback
+    - xc_domain_get_cpu_usage
+    - xc_domain_get_guest_width
+    - xc_domain_getinfo
+    - xc_domain_getinfolist (`XEN_SYSCTL_getdomaininfolist`). Used by qemu-dm.
+    - xc_domain_get_machine_address_size
+    - xc_domain_get_pod_target
+    - xc_domain_get_tsc_info
+    - xc_domain_hvm_getcontext
+    - xc_domain_hvm_getcontext_partial
+    - xc_domain_hvm_setcontext
+    - xc_domain_increase_reservation
+    - xc_domain_increase_reservation_exact
+    - xc_domain_iomem_permission
+    - xc_domain_ioport_mapping
+    - xc_domain_ioport_permission
+    - xc_domain_irq_permission
+    - xc_domain_maximum_gpfn
+    - xc_domain_max_vcpus
+    - xc_domain_memory_exchange_pages
+    - xc_domain_memory_mapping
+    - xc_domain_node_getaffinity
+    - xc_domain_node_setaffinity
+    - xc_domain_nr_gpfns
+    - xc_domain_p2m_audit
+    - xc_domain_pause
+    - xc_domain_pin_memory_cacheattr (`XEN_DOMCTL_pin_mem_cacheattr`). Used by qemu-dm.
+    - xc_domain_resume
+    - xc_domain_send_trigger
+    - xc_domain_set_access_required
+    - xc_domain_setdebugging
+    - xc_domain_sethandle
+    - xc_domain_set_machine_address_size
+    - xc_domain_set_max_evtchn
+    - xc_domain_setmaxmem (`XEN_DOMCTL_max_mem`). Used by qemu-dm.
+    - xc_domain_set_memmap_limit
+    - xc_domain_set_memory_map
+    - xc_domain_set_pod_target
+    - xc_domain_set_target
+    - xc_domain_set_time_offset
+    - xc_domain_set_tsc_info
+    - xc_domain_set_virq_handler
+    - xc_domain_setvnuma
+    - xc_domain_shutdown (`SCHEDOP_remote_shutd`). Used by qemu-dm.
+    - xc_domain_subscribe_for_suspend
+    - xc_domain_suppress_spurious_page_faults
+    - xc_domain_unbind_msi_irq
+    - xc_domain_unbind_pt_irq
+    - xc_domain_unbind_pt_spi_irq
+    - xc_domain_unpause
+    - xc_domain_update_msi_irq
+    - xc_enable_turbo
+    - xc_error_code_to_desc
+    - xc_ffs16
+    - xc_ffs32
+    - xc_ffs64
+    - xc_ffs8
+    - xc_flask_access
+    - xc_flask_add_device
+    - xc_flask_add_iomem
+    - xc_flask_add_ioport
+    - xc_flask_add_pirq
+    - xc_flask_avc_cachestats
+    - xc_flask_avc_hashstats
+    - xc_flask_context_to_sid
+    - xc_flask_del_device
+    - xc_flask_del_iomem
+    - xc_flask_del_ioport
+    - xc_flask_del_pirq
+    - xc_flask_getavc_threshold
+    - xc_flask_getbool_byid
+    - xc_flask_getbool_byname
+    - xc_flask_getenforce
+    - xc_flask_load
+    - xc_flask_op
+    - xc_flask_policyvers
+    - xc_flask_relabel_domain
+    - xc_flask_setavc_threshold
+    - xc_flask_setbool
+    - xc_flask_setenforce
+    - xc_flask_sid_to_context
+    - xc_flush_mmu_updates
+    - xc_get_cpufreq_avgfreq
+    - xc_get_cpufreq_para
+    - xc_get_cpuidle_max_cstate
+    - xc_getcpuinfo
+    - xc_get_cpumap_size
+    - xc_get_device_group
+    - xc_get_hvm_param
+    - xc_get_last_error
+    - xc_get_machine_memory_map. Used by kexec-tools
+    - xc_get_max_cpus. Used by kexec-tools
+    - xc_get_max_nodes
+    - xc_get_mem_access
+    - xc_get_nodemap_size
+    - xc_get_online_cpus
+    - xc_get_pfn_list
+    - xc_get_pfn_type_batch
+    - xc_get_tot_pages
+    - xc_get_vcpu_migration_delay
+    - xc_hvm_create_ioreq_server
+    - xc_hvm_destroy_ioreq_server
+    - xc_hvm_get_ioreq_server_info
+    - xc_hvm_inject_msi (`HVMOP_inject_msi`). Used by qemu-dm.
+    - xc_hvm_inject_trap
+    - xc_hvm_map_io_range_to_ioreq_server
+    - xc_hvm_map_pcidev_to_ioreq_server
+    - xc_hvm_modified_memory (`HVMOP_modified_memory`). Used by qemu-dm.
+    - xc_hvm_param_get
+    - xc_hvm_param_set
+    - xc_hvm_set_ioreq_server_state
+    - xc_hvm_set_isa_irq_level (`HVMOP_set_isa_irq_level`). Used by qemu-dm.
+    - xc_hvm_set_mem_type (`HVMOP_set_mem_type`). Used by qemu-dm.
+    - xc_hvm_set_pci_intx_level (`HVMOP_set_pci_intx_level`). Used by qemu-dm.
+    - xc_hvm_set_pci_link_route (`HVMOP_set_pci_link_route`). Used by qemu-dm.
+    - xc_hvm_track_dirty_vram (`HVMOP_track_dirty_vram`). Used by qemu-dm.
+    - xc_hvm_unmap_io_range_from_ioreq_server
+    - xc_hvm_unmap_pcidev_from_ioreq_server
+    - xc_lockprof_query
+    - xc_lockprof_query_number
+    - xc_lockprof_reset
+    - xc_machphys_mfn_list
+    - xc_make_page_below_4G
+    - xc_map_domain_meminfo
+    - xc_maximum_ram_page
+    - xc_mca_op
+    - xc_mem_access_disable_emulate
+    - xc_mem_access_enable_emulate
+    - xc_memalign
+    - xc_mem_paging_disable
+    - xc_mem_paging_enable
+    - xc_mem_paging_evict
+    - xc_mem_paging_load
+    - xc_mem_paging_nominate
+    - xc_mem_paging_prep
+    - xc_mem_paging_resume
+    - xc_memshr_add_to_physmap
+    - xc_memshr_audit
+    - xc_memshr_control
+    - xc_memshr_debug_gfn
+    - xc_memshr_debug_gref
+    - xc_memshr_domain_resume
+    - xc_memshr_nominate_gfn
+    - xc_memshr_nominate_gref
+    - xc_memshr_ring_disable
+    - xc_memshr_ring_enable
+    - xc_memshr_share_gfns
+    - xc_memshr_share_grefs
+    - xc_mmuext_op
+    - xc_monitor_disable
+    - xc_monitor_enable
+    - xc_monitor_mov_to_msr
+    - xc_monitor_resume
+    - xc_monitor_singlestep
+    - xc_monitor_software_breakpoint
+    - xc_monitor_write_ctrlreg
+    - xc_nodemap_alloc
+    - xc_numainfo
+    - xc_osdep_log
+    - xc_pcitopoinfo
+    - xc_perfc_query
+    - xc_perfc_query_number
+    - xc_perfc_reset
+    - xc_physdev_map_pirq
+    - xc_physdev_map_pirq_msi
+    - xc_physdev_pci_access_modify
+    - xc_physdev_unmap_pirq
+    - xc_physinfo
+    - xc_pm_get_cxstat
+    - xc_pm_get_max_cx
+    - xc_pm_get_max_px
+    - xc_pm_get_pxstat
+    - xc_pm_reset_cxstat
+    - xc_pm_reset_pxstat
+    - xc_psr_cmt_attach
+    - xc_psr_cmt_detach
+    - xc_psr_cmt_enabled
+    - xc_psr_cmt_get_data
+    - xc_psr_cmt_get_domain_rmid
+    - xc_psr_cmt_get_l3_cache_size
+    - xc_psr_cmt_get_l3_event_mask
+    - xc_psr_cmt_get_l3_upscaling_factor
+    - xc_psr_cmt_get_total_rmid
+    - xc_readconsolering
+    - xc_report
+    - xc_report_error
+    - xc_report_progress_single
+    - xc_report_progress_step
+    - xc_reportv
+    - xc_resource_op
+    - xc_sched_arinc653_schedule_get
+    - xc_sched_arinc653_schedule_set
+    - xc_sched_credit2_domain_get
+    - xc_sched_credit2_domain_set
+    - xc_sched_credit_domain_get
+    - xc_sched_credit_domain_set
+    - xc_sched_credit_params_get
+    - xc_sched_credit_params_set
+    - xc_sched_id
+    - xc_sched_rtds_domain_get
+    - xc_sched_rtds_domain_set
+    - xc_sedf_domain_get
+    - xc_sedf_domain_set
+    - xc_send_debug_keys
+    - xc_set_broken_page_p2m
+    - xc_set_cpufreq_gov
+    - xc_set_cpufreq_para
+    - xc_set_cpuidle_max_cstate
+    - xc_set_hvm_param (`HVMOP_set_param`). Used by qemu-dm.
+    - xc_set_mem_access
+    - xc_set_progress_prefix
+    - xc_set_sched_opt_smt
+    - xc_set_vcpu_migration_delay
+    - xc_shadow_control
+    - xc_sharing_freed_pages
+    - xc_sharing_used_frames
+    - xc_strerror
+    - xc_tbuf_disable
+    - xc_tbuf_enable
+    - xc_tbuf_get_size
+    - xc_tbuf_set_cpu_mask
+    - xc_tbuf_set_evt_mask
+    - xc_tbuf_set_size
+    - xc_test_assign_device
+    - xc_test_assign_dt_device
+    - xc_tmem_auth
+    - xc_tmem_control
+    - xc_tmem_control_oid
+    - xc_tmem_restore
+    - xc_tmem_restore_extra
+    - xc_tmem_save
+    - xc_tmem_save_done
+    - xc_tmem_save_extra
+    - xc_translate_foreign_address
+    - xc_unmap_domain_meminfo
+    - xc_vcpu_getaffinity
+    - xc_vcpu_getcontext
+    - xc_vcpu_getinfo
+    - xc_vcpu_setaffinity
+    - xc_vcpu_setcontext
+    - xc_version. Used by kexec-tools
+    - xc_vm_event_control
+    - xc_vm_event_enable
+    - xc_watchdog
+
+## `libxenguest`
+
+Gathered by:
+
+
+    $ objdump -T tools/libxc/libxenguest.so| awk '$4 ~ /\.text/ { print $7 }' | sort -u
+
+    - arch_setup_bootearly
+    - arch_setup_bootlate
+    - arch_setup_meminit
+    - cr3_to_mfn
+    - csum_page
+    - dhdr_type_to_str
+    - dump_bad_pseudophysmap_entry
+    - elf_access_ok
+    - elf_access_unsigned
+    - elf_call_log_callback
+    - elf_check_broken
+    - elf_get_ptr
+    - elf_init
+    - elf_is_elfbinary
+    - elf_load_binary
+    - elf_lookup_addr
+    - elf_mark_broken
+    - elf_memcpy_safe
+    - elf_memset_safe
+    - elf_note_desc
+    - elf_note_name
+    - elf_note_next
+    - elf_note_numeric
+    - elf_note_numeric_array
+    - elf_parse_binary
+    - elf_parse_bsdsyms
+    - elf_phdr_by_index
+    - elf_phdr_count
+    - elf_phdr_is_loadable
+    - elf_round_up
+    - elf_section_end
+    - elf_section_name
+    - elf_section_start
+    - elf_segment_end
+    - elf_segment_start
+    - elf_set_log
+    - elf_shdr_by_index
+    - elf_shdr_by_name
+    - elf_shdr_count
+    - elf_strfmt
+    - elf_strval
+    - elf_sym_by_index
+    - elf_sym_by_name
+    - elf_xen_parse
+    - elf_xen_parse_features
+    - elf_xen_parse_guest_info
+    - elf_xen_parse_note
+    - handle_tsc_info
+    - lz4_decompress_unknownoutputsize
+    - mfn_in_pseudophysmap
+    - mfn_to_cr3
+    - mfn_to_pfn
+    - pin_table
+    - populate_pfns
+    - read_qemu
+    - rec_type_to_str
+    - write_split_record
+    - write_tsc_info
+    - x86_pv_domain_info
+    - x86_pv_map_m2p
+    - xc_await_suspend
+    - xc_compression_add_page
+    - xc_compression_compress_pages
+    - xc_compression_create_context
+    - xc_compression_free_context
+    - xc_compression_reset_pagebuf
+    - xc_compression_uncompress_page
+    - xc_cpuid_apply_policy
+    - xc_cpuid_check
+    - xc_cpuid_set
+    - xc_cpuid_to_str
+    - xc_domain_get_native_protocol
+    - xc_domain_restore
+    - xc_domain_restore2
+    - xc_domain_save
+    - xc_domain_save2
+    - xc_dom_allocate
+    - xc_dom_alloc_page
+    - xc_dom_alloc_segment
+    - xc_dom_boot_domU_map
+    - xc_dom_boot_image
+    - xc_dom_boot_mem_init
+    - xc_dom_boot_xen_init
+    - xc_dom_build_image
+    - xc_dom_check_gzip
+    - xc_dom_compat_check
+    - xc_dom_devicetree_file
+    - xc_dom_devicetree_max_size
+    - xc_dom_devicetree_mem
+    - xc_dom_do_gunzip
+    - xc_dom_feature_translated
+    - xc_dom_find_arch_hooks
+    - xc_dom_gnttab_hvm_seed
+    - xc_dom_gnttab_init
+    - xc_dom_gnttab_seed
+    - xc_dom_kernel_check_size
+    - xc_dom_kernel_file
+    - xc_dom_kernel_max_size
+    - xc_dom_kernel_mem
+    - xc_dom_linux_build
+    - xc_dom_loginit
+    - xc_dom_log_memory_footprint
+    - xc_dom_malloc
+    - xc_dom_malloc_filemap
+    - xc_dom_malloc_page_aligned
+    - xc_dom_mem_init
+    - xc_dom_panic_func
+    - xc_dom_parse_image
+    - xc_dom_pfn_to_ptr
+    - xc_dom_pfn_to_ptr_retcount
+    - xc_dom_printf
+    - xc_dom_rambase_init
+    - xc_dom_ramdisk_check_size
+    - xc_dom_ramdisk_file
+    - xc_dom_ramdisk_max_size
+    - xc_dom_ramdisk_mem
+    - xc_dom_register_arch_hooks
+    - xc_dom_register_external
+    - xc_dom_register_loader
+    - xc_dom_release
+    - xc_dom_strdup
+    - xc_dom_try_gunzip
+    - xc_dom_unmap_all
+    - xc_dom_unmap_one
+    - xc_dom_update_guest_p2m
+    - xc_elf_set_logfile
+    - xc_exchange_page
+    - xc_get_bit_size
+    - xc_hvm_build
+    - xc_hvm_build_target_mem
+    - xc_inflate_buffer
+    - xc_linux_build
+    - xc_linux_build_mem
+    - xc_map_m2p
+    - xc_mark_page_offline
+    - xc_mark_page_online
+    - xc_query_page_offline_status
+    - xc_read_image
+    - xc_suspend_evtchn_init_exclusive
+    - xc_suspend_evtchn_init_sane
+    - xc_suspend_evtchn_release
+    - xc_try_lz4_decode
+
+# Consumers of `libxenctrl` functionality
+
+## `qemu`
+
+    $ nm tools/qemu-xen-dir-remote/i386-softmmu/qemu-system-i386 | grep \\bU.xc_
+
+    - xc_domain_add_to_physmap
+    - xc_domain_bind_pt_pci_irq
+    - xc_domain_create
+    - xc_domain_destroy
+    - xc_domain_getinfo
+    - xc_domain_ioport_mapping
+    - xc_domain_max_vcpus
+    - xc_domain_memory_mapping
+    - xc_domain_pin_memory_cacheattr
+    - xc_domain_populate_physmap_exact
+    - xc_domain_setmaxmem
+    - xc_domain_shutdown
+    - xc_domain_unbind_msi_irq
+    - xc_domain_unbind_pt_irq
+    - xc_domain_unpause
+    - xc_domain_update_msi_irq
+    - xc_evtchn_alloc_unbound
+    - xc_evtchn_bind_interdomain
+    - xc_evtchn_close
+    - xc_evtchn_fd
+    - xc_evtchn_notify
+    - xc_evtchn_open
+    - xc_evtchn_pending
+    - xc_evtchn_unbind
+    - xc_evtchn_unmask
+    - xc_get_hvm_param
+    - xc_hvm_inject_msi
+    - xc_hvm_modified_memory
+    - xc_hvm_set_isa_irq_level
+    - xc_hvm_set_mem_type
+    - xc_hvm_set_pci_intx_level
+    - xc_hvm_set_pci_link_route
+    - xc_hvm_track_dirty_vram
+    - xc_interface_close
+    - xc_interface_open
+    - xc_linux_build
+    - xc_map_foreign_bulk
+    - xc_map_foreign_pages
+    - xc_map_foreign_range
+    - xc_physdev_map_pirq
+    - xc_physdev_map_pirq_msi
+    - xc_physdev_unmap_pirq
+    - xc_set_hvm_param
+
+### By functional area
+
+As a reference, this is a split of the xc_ calls made by QEMU, based on
+functionality areas:
+
+* Device model
+    * xc_domain_add_to_physmap (`XENMEM_add_to_physmap`)
+    * xc_domain_getinfolist (`XEN_SYSCTL_getdomaininfolist`)
+    * xc_domain_pin_memory_cacheattr (`XEN_DOMCTL_pin_mem_cacheattr`)
+    * xc_domain_populate_physmap_exact (`XENMEM_populate_physmap`)
+    * xc_domain_setmaxmem (`XEN_DOMCTL_max_mem`)
+    * xc_domain_shutdown (`SCHEDOP_remote_shutdown`)
+    * xc_evtchn_bind_interdomain (`IOCTL_EVTCHN_BIND_INTERDOMAIN`)
+    * xc_evtchn_close (`close(2)`)
+    * xc_evtchn_fd
+    * xc_evtchn_notify (`IOCTL_EVTCHN_NOTIFY`)
+    * xc_evtchn_open (`open(2)`)
+    * xc_evtchn_pending (`read(2)`)
+    * xc_evtchn_unmask (`write(2)`)
+    * xc_hvm_inject_msi (`HVMOP_inject_msi`)
+    * xc_hvm_modified_memory (`HVMOP_modified_memory`)
+    * xc_hvm_set_isa_irq_level (`HVMOP_set_isa_irq_level`)
+    * xc_hvm_set_mem_type (`HVMOP_set_mem_type`)
+    * xc_hvm_set_pci_intx_level (`HVMOP_set_pci_intx_level`)
+    * xc_hvm_set_pci_link_route (`HVMOP_set_pci_link_route`)
+    * xc_hvm_track_dirty_vram (`HVMOP_track_dirty_vram`)
+    * xc_interface_close
+    * xc_interface_open
+    * xc_map_foreign_bulk (`IOCTL_PRIVCMD_MMAPBATCH_V2`)
+    * xc_map_foreign_range (`IOCTL_PRIVCMD_MMAP...`)
+    * xc_set_hvm_param (`HVMOP_set_param`)
+* PCI Passthrough
+    * xc_domain_bind_pt_pci_irq
+    * xc_domain_ioport_mapping
+    * xc_domain_memory_mapping
+    * xc_domain_unbind_msi_irq
+    * xc_domain_unbind_pt_irq
+    * xc_domain_update_msi_irq
+    * xc_physdev_map_pirq
+    * xc_physdev_map_pirq_msi
+    * xc_physdev_unmap_pirq
+* PV backends
+    * xc_evtchn_bind_interdomain (`IOCTL_EVTCHN_BIND_INTERDOMAIN`)
+    * xc_evtchn_notify (`IOCTL_EVTCHN_NOTIFY`)
+    * xc_evtchn_open (`open(2)`)
+    * xc_evtchn_pending (`read(2)`)
+    * xc_evtchn_unbind
+    * xc_evtchn_unmask (`write(2)`)
+    * xc_gnttab_close
+    * xc_gnttab_map_grant_ref
+    * xc_gnttab_munmap
+    * xc_gnttab_open
+    * xc_gnttab_set_max_grants
+    * xc_map_foreign_pages (`IOCTL_PRIVCMD_MMAP...`)
+    * xc_map_foreign_range (`IOCTL_PRIVCMD_MMAP...`)
+
+## `kexec-tools`
+
+    - xc__hypercall_buffer_array_alloc
+    - xc_get_machine_memory_map
+    - xc_get_max_cpus
+    - xc_hypercall_buffer_array_create
+    - xc_hypercall_buffer_array_destroy
+    - xc_interface_close
+    - xc_interface_open
+    - xc_kexec_exec
+    - xc_kexec_get_range
+    - xc_kexec_load
+    - xc_kexec_unload
+    - xc_version
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH XEN v2 02/15] tools/Rules.mk: Properly handle libraries with recursive dependcies.
  2015-07-15 15:46 [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries Ian Campbell
  2015-07-15 15:46 ` [PATCH XEN v2 01/15] docs: Partial toolstack library API/ABI stabilisation Ian Campbell
@ 2015-07-15 15:46 ` Ian Campbell
  2015-07-15 15:46 ` [PATCH XEN v2 03/15] tools: Refactor "xentoollog" into its own library Ian Campbell
                   ` (25 subsequent siblings)
  27 siblings, 0 replies; 55+ messages in thread
From: Ian Campbell @ 2015-07-15 15:46 UTC (permalink / raw)
  To: ian.jackson, wei.liu2, xen-devel
  Cc: roger.pau, Ian Campbell, stefano.stabellini

In tree libraries which link against other in tree libraries in a way
which is opaque to their callers need special handling, specifically
correct use of -Wl,-rpath-link for the recusively used libraries.

Currently this is rather simple, but up coming changes are going to
introduce transitive dependencies more than 1 step deep.

Introduce a SHDEPS idiom to contain all the recursive deps for a
library and include those in both LDLIBS (for linking) and SHLIB (for
recursive uses).

Try and document the whole thing.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
---
 tools/Rules.mk | 74 ++++++++++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 62 insertions(+), 12 deletions(-)

diff --git a/tools/Rules.mk b/tools/Rules.mk
index 2c422bd..28e84e6 100644
--- a/tools/Rules.mk
+++ b/tools/Rules.mk
@@ -34,25 +34,72 @@ INSTALL_SHLIB = : install-shlib-unsupported-fail
 SYMLINK_SHLIB = : symlink-shlib-unsupported-fail
 endif
 
+# Compiling and linking against in tree libraries.
+#
+# In order to compile and link against an in-tree library various
+# cpp/compiler/linker options are required.
+#
+# For example consider a library "libfoo" which itself uses two other
+# libraries:
+#  libbar - whose use is entirely internal to libfoo and not exposed
+#           to users of libfoo at all.
+#  libbaz - whose use is entirely internal to libfoo but libfoo's
+#           public headers include libbaz's one or more of libbaz's
+#           public headers. Users of libfoo are therefore transitively
+#           using libbaz's header but not linking against libbaz.
+#
+# SHDEPS_libfoo: Flags for linking recursive dependencies of
+#                libfoo. Must contain SHLIB for every library which
+#                libfoo links against. So must contain both
+#                $(SHLIB_libbar) and $(SHLIB_libbaz).
+#
+# SHLIB_libfoo: Flags for recursively linking against libfoo. Must
+#               contains SHDEPS_libfoo and:
+#                   -Wl,-rpath-link=<directory containing libfoo.so>
+#
+# CFLAGS_libfoo: Flags for compiling against libfoo. Must add the
+#                directories containing libfoo's headers to the
+#                include path. Must recursively include
+#                $(CFLAGS_libbaz), to satisfy the transitive inclusion
+#                of the headers but not $(CFLAGS_libbar) since none of
+#                libbar's headers are required to build against
+#                libfoo.
+#
+# LDLIBS_libfoo: Flags for linking against libfoo. Must contain
+#                $(SHDEPS_libfoo) and the path to libfoo.so
+#
+# Consumers of libfoo should include $(CFLAGS_libfoo) and
+# $(LDLIBS_libfoo) in their appropriate directories. They should not
+# include any CFLAGS or LDLIBS relating to libbar or libbaz unless
+# they use those libraries directly (not via libfoo) too.
+#
+# Consumers of libfoo should not directly use $(SHDEPS_libfoo) or
+# $(SHLIB_libfoo)
+
 CFLAGS_libxenctrl = -I$(XEN_LIBXC)/include $(CFLAGS_xeninclude)
+SHDEPS_libxenctrl =
 LDLIBS_libxenctrl = $(XEN_LIBXC)/libxenctrl$(libextension)
 SHLIB_libxenctrl  = -Wl,-rpath-link=$(XEN_LIBXC)
 
 CFLAGS_libxenguest = -I$(XEN_LIBXC)/include $(CFLAGS_xeninclude)
-LDLIBS_libxenguest = $(XEN_LIBXC)/libxenguest$(libextension)
-SHLIB_libxenguest  = -Wl,-rpath-link=L$(XEN_LIBXC)
+SHDEPS_libxenguest =
+LDLIBS_libxenguest = $(SHDEPS_libxenguest) $(XEN_LIBXC)/libxenguest$(libextension)
+SHLIB_libxenguest  = $(SHDEPS_libxenguest) -Wl,-rpath-link=L$(XEN_LIBXC)
 
 CFLAGS_libxenstore = -I$(XEN_XENSTORE)/include $(CFLAGS_xeninclude)
-LDLIBS_libxenstore = $(XEN_XENSTORE)/libxenstore$(libextension)
-SHLIB_libxenstore  = -Wl,-rpath-link=$(XEN_XENSTORE)
+SHDEPS_libxenstore =
+LDLIBS_libxenstore = $(SHDEPS_libxenguest) $(XEN_XENSTORE)/libxenstore$(libextension)
+SHLIB_libxenstore  = $(SHDEPS_libxenguest) -Wl,-rpath-link=$(XEN_XENSTORE)
 
 CFLAGS_libxenstat  = -I$(XEN_LIBXENSTAT)
-LDLIBS_libxenstat  = $(SHLIB_libxenctrl) $(SHLIB_libxenstore) $(XEN_LIBXENSTAT)/libxenstat$(libextension)
-SHLIB_libxenstat  = -Wl,-rpath-link=$(XEN_LIBXENSTAT)
+SHDEPS_libxenstat  = $(SHLIB_libxenctrl) $(SHLIB_libxenstore)
+LDLIBS_libxenstat  = $(SHDEPS_libxenstat) $(XEN_LIBXENSTAT)/libxenstat$(libextension)
+SHLIB_libxenstat   = $(SHDEPS_libxenstat) -Wl,-rpath-link=$(XEN_LIBXENSTAT)
 
 CFLAGS_libxenvchan = -I$(XEN_LIBVCHAN)
-LDLIBS_libxenvchan = $(SHLIB_libxenctrl) $(SHLIB_libxenstore) $(XEN_LIBVCHAN)/libxenvchan$(libextension)
-SHLIB_libxenvchan  = -Wl,-rpath-link=$(XEN_LIBVCHAN)
+SHDEPS_libxenvchan = $(SHLIB_libxenctrl) $(SHLIB_libxenstore)
+LDLIBS_libxenvchan = $(SHDEPS_libxenvchan) $(XEN_LIBVCHAN)/libxenvchan$(libextension)
+SHLIB_libxenvchan  = $(SHDEPS_libxenvchan) -Wl,-rpath-link=$(XEN_LIBVCHAN)
 
 ifeq ($(debug),y)
 # Disable optimizations and enable debugging information for macros
@@ -65,17 +112,20 @@ LIBXL_BLKTAP ?= $(CONFIG_BLKTAP2)
 
 ifeq ($(LIBXL_BLKTAP),y)
 CFLAGS_libblktapctl = -I$(XEN_BLKTAP2)/control -I$(XEN_BLKTAP2)/include $(CFLAGS_xeninclude)
-LDLIBS_libblktapctl = $(XEN_BLKTAP2)/control/libblktapctl$(libextension)
-SHLIB_libblktapctl  = -Wl,-rpath-link=$(XEN_BLKTAP2)/control
+SHDEPS_libblktapctl =
+LDLIBS_libblktapctl = $(SHDEPS_libblktapctl) $(XEN_BLKTAP2)/control/libblktapctl$(libextension)
+SHLIB_libblktapctl  = $(SHDEPS_libblktapctl) -Wl,-rpath-link=$(XEN_BLKTAP2)/control
 else
 CFLAGS_libblktapctl =
+SHDEPS_libblktapctl =
 LDLIBS_libblktapctl =
 SHLIB_libblktapctl  =
 endif
 
 CFLAGS_libxenlight = -I$(XEN_XENLIGHT) $(CFLAGS_libxenctrl) $(CFLAGS_xeninclude)
-LDLIBS_libxenlight = $(XEN_XENLIGHT)/libxenlight$(libextension) $(SHLIB_libxenctrl) $(SHLIB_libxenstore) $(SHLIB_libblktapctl)
-SHLIB_libxenlight  = -Wl,-rpath-link=$(XEN_XENLIGHT)
+SHDEPS_libxenlight = $(SHLIB_libxenctrl) $(SHLIB_libxenstore) $(SHLIB_libblktapctl)
+LDLIBS_libxenlight = $(SHDEPS_libxenlight) $(XEN_XENLIGHT)/libxenlight$(libextension)
+SHLIB_libxenlight  = $(SHDEPS_libxenlight) -Wl,-rpath-link=$(XEN_XENLIGHT)
 
 CFLAGS += -D__XEN_TOOLS__
 
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH XEN v2 03/15] tools: Refactor "xentoollog" into its own library
  2015-07-15 15:46 [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries Ian Campbell
  2015-07-15 15:46 ` [PATCH XEN v2 01/15] docs: Partial toolstack library API/ABI stabilisation Ian Campbell
  2015-07-15 15:46 ` [PATCH XEN v2 02/15] tools/Rules.mk: Properly handle libraries with recursive dependcies Ian Campbell
@ 2015-07-15 15:46 ` Ian Campbell
  2015-07-15 15:46 ` [PATCH XEN v2 04/15] tools/libxc: Remove osdep indirection for xc_evtchn Ian Campbell
                   ` (24 subsequent siblings)
  27 siblings, 0 replies; 55+ messages in thread
From: Ian Campbell @ 2015-07-15 15:46 UTC (permalink / raw)
  To: ian.jackson, wei.liu2, xen-devel
  Cc: roger.pau, Ian Campbell, stefano.stabellini

In attempting to disaggregate libxenctrl I found that many of the
pieces were going to want access to this library, so split it out (as
it probably should always have been).

Various build adjustments are needed. In particular things which use
xtl_* themselves now need to explicity link against the library.

This has a nice side effect which is that users of libxl no longer
need to link against libxenctrl just to create a logger, which was
counter to the principal that applications using libxl shouldn't be
required to look behind the curtain. This means that xl no longer
links against libxenctrl.

The new library uses a version script to ensure that only expected
symbols are exported and to version them such that ABI guarantees can
be kept in the future.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>

---
Must be applied with:

- "qemu-xen-traditional: Use xentoollog as a separate library" and a
  corresponding QEMU_TAG update folded here.
- "mini-os: Include libxentoollog with libxc" and a corresponding bump
  to MINIOS_UPSTREAM_REVISION folded in here.

v2: Update doc at same time
---
 .gitignore                               |   1 +
 docs/misc/toolstack-library-abis.pandoc  |  36 +++---
 stubdom/Makefile                         |  20 +++-
 stubdom/grub/Makefile                    |   1 +
 tools/Makefile                           |   3 +
 tools/Rules.mk                           |  14 ++-
 tools/libxc/Makefile                     |   7 +-
 tools/libxc/include/xentoollog.h         | 137 ----------------------
 tools/libxc/xtl_core.c                   |  84 --------------
 tools/libxc/xtl_logger_stdio.c           | 193 -------------------------------
 tools/libxentoollog/Makefile             |  59 ++++++++++
 tools/libxentoollog/include/xentoollog.h | 137 ++++++++++++++++++++++
 tools/libxentoollog/libxentoollog.map    |  12 ++
 tools/libxentoollog/xtl_core.c           |  84 ++++++++++++++
 tools/libxentoollog/xtl_logger_stdio.c   | 193 +++++++++++++++++++++++++++++++
 tools/libxl/Makefile                     |  15 +--
 tools/ocaml/Makefile.rules               |  26 ++---
 tools/ocaml/libs/xentoollog/Makefile     |   6 +-
 tools/ocaml/libs/xentoollog/genlevels.py |   2 +-
 tools/python/setup.py                    |   5 +-
 tools/xenpaging/Makefile                 |   2 +-
 21 files changed, 571 insertions(+), 466 deletions(-)
 delete mode 100644 tools/libxc/include/xentoollog.h
 delete mode 100644 tools/libxc/xtl_core.c
 delete mode 100644 tools/libxc/xtl_logger_stdio.c
 create mode 100644 tools/libxentoollog/Makefile
 create mode 100644 tools/libxentoollog/include/xentoollog.h
 create mode 100644 tools/libxentoollog/libxentoollog.map
 create mode 100644 tools/libxentoollog/xtl_core.c
 create mode 100644 tools/libxentoollog/xtl_logger_stdio.c

diff --git a/.gitignore b/.gitignore
index 464f3f4..e56487a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -59,6 +59,7 @@ stubdom/gcc-*
 stubdom/include
 stubdom/ioemu
 stubdom/xenstore
+stubdom/libxentoollog-*
 stubdom/libxc-*
 stubdom/lwip-*
 stubdom/mini-os-*
diff --git a/docs/misc/toolstack-library-abis.pandoc b/docs/misc/toolstack-library-abis.pandoc
index c24be81..68e6742 100644
--- a/docs/misc/toolstack-library-abis.pandoc
+++ b/docs/misc/toolstack-library-abis.pandoc
@@ -91,6 +91,26 @@ rationalisation of what lives where.
 
 Not a candidate for API/ABI stability at this point.
 
+# Stable libraries
+ 
+These libraries will provide a stable API to all consumers going
+forward. They can be mixed and matched with Xen version.
+
+## `libxentoollog`: logging
+
+The following do not depend on any underlying Xen functionality.
+
+Interface                     Known external users
+----------------------------- --------------------
+`xtl_createlogger_stdiostream`
+`xtl_level_to_string`
+`xtl_log`
+`xtl_logger_destroy`
+`xtl_logv`
+`xtl_progress`
+`xtl_stdiostream_adjust_flags`
+`xtl_stdiostream_set_minlevel`
+
 # Unstable libraries
 
 These libraries do not provide a stable interface and are required to
@@ -124,22 +144,6 @@ Notes:
   via `...` (often a macro).
 * There are lots of static functions in the `xc_*` namespace.
 
-### Logging
-
-The following are already logically somewhat separate. They do not
-depend on any underlying Xen functionality.
-
-Interface                     Known external users
------------------------------ --------------------
-`xtl_createlogger_stdiostream`
-`xtl_level_to_string`
-`xtl_log`
-`xtl_logger_destroy`
-`xtl_logv`
-`xtl_progress`
-`xtl_stdiostream_adjust_flags`
-`xtl_stdiostream_set_minlevel`
-
 ### Basic interface
 
     - xc_interface_close
diff --git a/stubdom/Makefile b/stubdom/Makefile
index faa7c21..b8b0d43 100644
--- a/stubdom/Makefile
+++ b/stubdom/Makefile
@@ -313,6 +313,11 @@ mk-headers-$(XEN_TARGET_ARCH): $(IOEMU_LINKFARM_TARGET)
 	  ln -sf $(wildcard $(XEN_ROOT)/tools/include/xen-foreign/*) include/xen-foreign/ && \
 	  $(MAKE) DESTDIR= -C include/xen-foreign/ && \
 	  ( [ -h include/xen/foreign ] || ln -sf ../xen-foreign include/xen/foreign )
+	mkdir -p libxentoollog-$(XEN_TARGET_ARCH)
+	[ -h libxentoollog-$(XEN_TARGET_ARCH)/Makefile ] || ( cd libxentoollog-$(XEN_TARGET_ARCH) && \
+	  ln -sf $(XEN_ROOT)/tools/libxentoollog/include/*.h . && \
+	  ln -sf $(XEN_ROOT)/tools/libxentoollog/*.c . && \
+	  ln -sf $(XEN_ROOT)/tools/libxentoollog/Makefile . )
 	mkdir -p libxc-$(XEN_TARGET_ARCH)
 	[ -h libxc-$(XEN_TARGET_ARCH)/Makefile ] || ( cd libxc-$(XEN_TARGET_ARCH) && \
 	  ln -sf $(XEN_ROOT)/tools/libxc/*.h . && \
@@ -336,12 +341,23 @@ $(TARGETS_MINIOS): mini-os-%:
 	done
 
 #######
+# libxentoollog
+#######
+
+.PHONY: libxentoollog
+libxentoollog: libxentoollog-$(XEN_TARGET_ARCH)/libxentoollog.a
+libxentoollog-$(XEN_TARGET_ARCH)/libxentoollog.a: $(NEWLIB_STAMPFILE)
+	$(MAKE) -C $(XEN_ROOT)/tools/include
+	$(MAKE) DESTDIR= -C $(MINI_OS) links
+	CPPFLAGS="$(TARGET_CPPFLAGS)" CFLAGS="$(TARGET_CFLAGS)" $(MAKE) DESTDIR= -C libxentoollog-$(XEN_TARGET_ARCH)
+
+#######
 # libxc
 #######
 
 .PHONY: libxc
 libxc: libxc-$(XEN_TARGET_ARCH)/libxenctrl.a libxc-$(XEN_TARGET_ARCH)/libxenguest.a
-libxc-$(XEN_TARGET_ARCH)/libxenctrl.a: cross-zlib
+libxc-$(XEN_TARGET_ARCH)/libxenctrl.a: libxentoollog cross-zlib
 	$(MAKE) -C $(XEN_ROOT)/tools/include
 	$(MAKE) DESTDIR= -C $(MINI_OS) links
 	CPPFLAGS="$(TARGET_CPPFLAGS)" CFLAGS="$(TARGET_CFLAGS)" $(MAKE) DESTDIR= CONFIG_LIBXC_MINIOS=y -C libxc-$(XEN_TARGET_ARCH)
@@ -519,6 +535,7 @@ clean:
 	$(MAKE) -C vtpmmgr clean
 	rm -fr grub-$(XEN_TARGET_ARCH)
 	rm -f $(STUBDOMPATH)
+	[ ! -e libxentoollog-$(XEN_TARGET_ARCH)/Makefile ] || $(MAKE) DESTDIR= -C libxentoollog-$(XEN_TARGET_ARCH) clean
 	[ ! -e libxc-$(XEN_TARGET_ARCH)/Makefile ] || $(MAKE) DESTDIR= -C libxc-$(XEN_TARGET_ARCH) clean
 	-[ ! -d ioemu ] || $(MAKE) DESTDIR= -C ioemu clean
 	-[ ! -d xenstore ] || $(MAKE) DESTDIR= -C xenstore clean
@@ -529,6 +546,7 @@ crossclean: clean
 	rm -fr $(CROSS_ROOT)
 	rm -fr newlib-$(XEN_TARGET_ARCH)
 	rm -fr zlib-$(XEN_TARGET_ARCH) pciutils-$(XEN_TARGET_ARCH)
+	rm -fr libxentoollog-$(XEN_TARGET_ARCH)
 	rm -fr libxc-$(XEN_TARGET_ARCH) ioemu xenstore
 	rm -fr gmp-$(XEN_TARGET_ARCH)
 	rm -fr polarssl-$(XEN_TARGET_ARCH)
diff --git a/stubdom/grub/Makefile b/stubdom/grub/Makefile
index 934cc4c..4969274 100644
--- a/stubdom/grub/Makefile
+++ b/stubdom/grub/Makefile
@@ -5,6 +5,7 @@ vpath %.c ../grub-upstream
 
 BOOT=$(OBJ_DIR)/boot-$(XEN_TARGET_ARCH).o
 
+DEF_CPPFLAGS += -I$(XEN_ROOT)/tools/libxentoollog/include
 DEF_CPPFLAGS += -I$(XEN_ROOT)/tools/libxc/include -I$(XEN_ROOT)/tools/include -I.
 DEF_CPPFLAGS += -I../grub-upstream/stage1
 DEF_CPPFLAGS += -I../grub-upstream/stage2
diff --git a/tools/Makefile b/tools/Makefile
index 45cb4b2..777591a 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -3,6 +3,7 @@ include $(XEN_ROOT)/tools/Rules.mk
 
 SUBDIRS-y :=
 SUBDIRS-y += include
+SUBDIRS-y += libxentoollog
 SUBDIRS-y += libxc
 SUBDIRS-$(FLASK_ENABLE) += flask
 SUBDIRS-y += xenstore
@@ -248,12 +249,14 @@ subdir-all-qemu-xen-dir: qemu-xen-dir-find
 		--includedir=$(LIBEXEC_INC) \
 		--source-path=$$source \
 		--extra-cflags="-I$(XEN_ROOT)/tools/include \
+		-I$(XEN_ROOT)/tools/libxentoollog/include \
 		-I$(XEN_ROOT)/tools/libxc/include \
 		-I$(XEN_ROOT)/tools/xenstore/include \
 		-I$(XEN_ROOT)/tools/xenstore/compat/include \
 		$(EXTRA_CFLAGS_QEMU_XEN)" \
 		--extra-ldflags="-L$(XEN_ROOT)/tools/libxc \
 		-L$(XEN_ROOT)/tools/xenstore \
+		-Wl,-rpath-link=$(XEN_ROOT)/tools/libxentoollog \
 		$(QEMU_UPSTREAM_RPATH)" \
 		--bindir=$(LIBEXEC_BIN) \
 		--datadir=$(SHAREDIR)/qemu-xen \
diff --git a/tools/Rules.mk b/tools/Rules.mk
index 28e84e6..11227c7 100644
--- a/tools/Rules.mk
+++ b/tools/Rules.mk
@@ -10,6 +10,7 @@ export _INSTALL := $(INSTALL)
 INSTALL = $(XEN_ROOT)/tools/cross-install
 
 XEN_INCLUDE        = $(XEN_ROOT)/tools/include
+XEN_LIBXENTOOLLOG  = $(XEN_ROOT)/tools/libxentoollog
 XEN_LIBXC          = $(XEN_ROOT)/tools/libxc
 XEN_XENLIGHT       = $(XEN_ROOT)/tools/libxl
 XEN_XENSTORE       = $(XEN_ROOT)/tools/xenstore
@@ -76,10 +77,15 @@ endif
 # Consumers of libfoo should not directly use $(SHDEPS_libfoo) or
 # $(SHLIB_libfoo)
 
-CFLAGS_libxenctrl = -I$(XEN_LIBXC)/include $(CFLAGS_xeninclude)
-SHDEPS_libxenctrl =
-LDLIBS_libxenctrl = $(XEN_LIBXC)/libxenctrl$(libextension)
-SHLIB_libxenctrl  = -Wl,-rpath-link=$(XEN_LIBXC)
+CFLAGS_libxentoollog = -I$(XEN_LIBXENTOOLLOG)/include $(CFLAGS_xeninclude)
+SHDEPS_libxentoollog =
+LDLIBS_libxentoollog = $(XEN_LIBXENTOOLLOG)/libxentoollog$(libextension)
+SHLIB_libxentoollog  = -Wl,-rpath-link=$(XEN_LIBXENTOOLLOG)
+
+CFLAGS_libxenctrl = -I$(XEN_LIBXC)/include $(CFLAGS_libxentoollog) $(CFLAGS_xeninclude)
+SHDEPS_libxenctrl = $(SHLIB_libxentoollog) 
+LDLIBS_libxenctrl = $(SHDEPS_libxenctrl) $(XEN_LIBXC)/libxenctrl$(libextension)
+SHLIB_libxenctrl  = $(SHDEPS_libxenctrl) -Wl,-rpath-link=$(XEN_LIBXC)
 
 CFLAGS_libxenguest = -I$(XEN_LIBXC)/include $(CFLAGS_xeninclude)
 SHDEPS_libxenguest =
diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile
index 1aec848..feb6125 100644
--- a/tools/libxc/Makefile
+++ b/tools/libxc/Makefile
@@ -38,8 +38,6 @@ CTRL_SRCS-y       += xc_memshr.c
 CTRL_SRCS-y       += xc_hcall_buf.c
 CTRL_SRCS-y       += xc_foreign_memory.c
 CTRL_SRCS-y       += xc_kexec.c
-CTRL_SRCS-y       += xtl_core.c
-CTRL_SRCS-y       += xtl_logger_stdio.c
 CTRL_SRCS-y       += xc_resource.c
 CTRL_SRCS-$(CONFIG_X86) += xc_psr.c
 CTRL_SRCS-$(CONFIG_X86) += xc_pagetab.c
@@ -113,6 +111,7 @@ CFLAGS   += -I. -I./include $(CFLAGS_xeninclude)
 CFLAGS-$(CONFIG_Linux) += -D_GNU_SOURCE
 
 CFLAGS	+= $(PTHREAD_CFLAGS)
+CFLAGS	+= $(CFLAGS_libxentoollog)
 
 CTRL_LIB_OBJS := $(patsubst %.c,%.o,$(CTRL_SRCS-y))
 CTRL_PIC_OBJS := $(patsubst %.c,%.opic,$(CTRL_SRCS-y))
@@ -166,7 +165,7 @@ install: build
 	$(INSTALL_DATA) libxenctrl.a $(DESTDIR)$(libdir)
 	$(SYMLINK_SHLIB) libxenctrl.so.$(MAJOR).$(MINOR) $(DESTDIR)$(libdir)/libxenctrl.so.$(MAJOR)
 	$(SYMLINK_SHLIB) libxenctrl.so.$(MAJOR) $(DESTDIR)$(libdir)/libxenctrl.so
-	$(INSTALL_DATA) include/xenctrl.h include/xenctrlosdep.h include/xentoollog.h $(DESTDIR)$(includedir)
+	$(INSTALL_DATA) include/xenctrl.h include/xenctrlosdep.h $(DESTDIR)$(includedir)
 	$(INSTALL_SHLIB) libxenguest.so.$(MAJOR).$(MINOR) $(DESTDIR)$(libdir)
 	$(INSTALL_DATA) libxenguest.a $(DESTDIR)$(libdir)
 	$(SYMLINK_SHLIB) libxenguest.so.$(MAJOR).$(MINOR) $(DESTDIR)$(libdir)/libxenguest.so.$(MAJOR)
@@ -209,7 +208,7 @@ libxenctrl.so.$(MAJOR): libxenctrl.so.$(MAJOR).$(MINOR)
 	$(SYMLINK_SHLIB) $< $@
 
 libxenctrl.so.$(MAJOR).$(MINOR): $(CTRL_PIC_OBJS)
-	$(CC) $(LDFLAGS) $(PTHREAD_LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenctrl.so.$(MAJOR) $(SHLIB_LDFLAGS) -o $@ $^ $(DLOPEN_LIBS) $(PTHREAD_LIBS) $(APPEND_LDFLAGS)
+	$(CC) $(LDFLAGS) $(PTHREAD_LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenctrl.so.$(MAJOR) $(SHLIB_LDFLAGS) -o $@ $^ $(LDLIBS_libxentoollog) $(DLOPEN_LIBS) $(PTHREAD_LIBS) $(APPEND_LDFLAGS)
 
 # libxenguest
 
diff --git a/tools/libxc/include/xentoollog.h b/tools/libxc/include/xentoollog.h
deleted file mode 100644
index 85d3da9..0000000
--- a/tools/libxc/include/xentoollog.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * xentoollog.h
- *
- * Copyright (c) 2010 Citrix
- * Part of a generic logging interface used by various dom0 userland libraries.
- *
- * This library 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 of the License.
- *
- * This library 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.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#ifndef XENTOOLLOG_H
-#define XENTOOLLOG_H
-
-#include <stdio.h>
-#include <stdarg.h>
-
-
-/*---------- common declarations and types ----------*/
-
-typedef enum xentoollog_level {
-    XTL_NONE, /* sentinel etc, never used for logging */
-    XTL_DEBUG,
-    XTL_VERBOSE,
-    XTL_DETAIL,
-    XTL_PROGRESS, /* also used for "progress" messages */
-    XTL_INFO,
-    XTL_NOTICE,
-    XTL_WARN,
-    XTL_ERROR,
-    XTL_CRITICAL,
-    XTL_NUM_LEVELS
-} xentoollog_level;
-
-typedef struct xentoollog_logger xentoollog_logger;
-struct xentoollog_logger {
-    void (*vmessage)(struct xentoollog_logger *logger,
-                     xentoollog_level level,
-                     int errnoval /* or -1 */,
-                     const char *context /* eg "xc", "xl", may be 0 */,
-                     const char *format /* without level, context, \n */,
-                     va_list al)
-         __attribute__((format(printf,5,0)));
-    void (*progress)(struct xentoollog_logger *logger,
-                     const char *context /* see above */,
-                     const char *doing_what /* no \r,\n */,
-                     int percent, unsigned long done, unsigned long total)
-         /* null function pointer is ok.
-          * will always be called with done==0 for each new
-          * context/doing_what */;
-    void (*destroy)(struct xentoollog_logger *logger);
-    /* each logger can put its necessary data here */
-};
-
-
-/*---------- facilities for consuming log messages ----------*/
-
-#define XTL_STDIOSTREAM_SHOW_PID            001u
-#define XTL_STDIOSTREAM_SHOW_DATE           002u
-#define XTL_STDIOSTREAM_HIDE_PROGRESS       004u
-#define XTL_STDIOSTREAM_PROGRESS_USE_CR     010u /* default is to */
-#define XTL_STDIOSTREAM_PROGRESS_NO_CR      020u /* use \r to ttys */
-
-typedef struct xentoollog_logger_stdiostream  xentoollog_logger_stdiostream;
-
-xentoollog_logger_stdiostream *xtl_createlogger_stdiostream
-        (FILE *f, xentoollog_level min_level, unsigned flags);
-    /* may return 0 if malloc fails, in which case error was logged */
-    /* destroy on this logger does not close the file */
-
-void xtl_stdiostream_set_minlevel(xentoollog_logger_stdiostream*,
-                                  xentoollog_level min_level);
-void xtl_stdiostream_adjust_flags(xentoollog_logger_stdiostream*,
-                                  unsigned set_flags, unsigned clear_flags);
-  /* if set_flags and clear_flags overlap, set_flags takes precedence */
-
-void xtl_logger_destroy(struct xentoollog_logger *logger /* 0 is ok */);
-
-
-/*---------- facilities for generating log messages ----------*/
-
-void xtl_logv(struct xentoollog_logger *logger,
-              xentoollog_level level,
-              int errnoval /* or -1 */,
-              const char *context /* eg "xc", "xenstore", "xl", may be 0 */,
-              const char *format /* does not contain \n */,
-              va_list) __attribute__((format(printf,5,0)));
-
-void xtl_log(struct xentoollog_logger *logger,
-             xentoollog_level level,
-             int errnoval /* or -1 */,
-             const char *context /* eg "xc", "xenstore", "xl" */,
-             const char *format /* does not contain \n */,
-             ...) __attribute__((format(printf,5,6)));
-
-void xtl_progress(struct xentoollog_logger *logger,
-                  const char *context /* see above, may be 0 */,
-                  const char *doing_what,
-                  unsigned long done, unsigned long total);
-
-
-/*---------- facilities for defining log message consumers ----------*/
-
-const char *xtl_level_to_string(xentoollog_level); /* never fails */
-
-
-#define XTL_NEW_LOGGER(LOGGER,buffer) ({                                \
-    xentoollog_logger_##LOGGER *new_consumer;                           \
-                                                                        \
-    (buffer).vtable.vmessage = LOGGER##_vmessage;                       \
-    (buffer).vtable.progress = LOGGER##_progress;                       \
-    (buffer).vtable.destroy  = LOGGER##_destroy;                        \
-                                                                        \
-    new_consumer = malloc(sizeof(*new_consumer));                       \
-    if (!new_consumer) {                                                \
-        xtl_log((xentoollog_logger*)&buffer,                            \
-                XTL_CRITICAL, errno, "xtl",                             \
-                "failed to allocate memory for new message logger");    \
-    } else {                                                            \
-        *new_consumer = buffer;                                         \
-    }                                                                   \
-                                                                        \
-    new_consumer;                                                       \
-});
-
-
-#endif /* XENTOOLLOG_H */
diff --git a/tools/libxc/xtl_core.c b/tools/libxc/xtl_core.c
deleted file mode 100644
index 73add92..0000000
--- a/tools/libxc/xtl_core.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * xtl_core.c
- *
- * core code including functions for generating log messages
- *
- * Copyright (c) 2010 Citrix
- * Part of a generic logging interface used by various dom0 userland libraries.
- *
- * This library 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 of the License.
- *
- * This library 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.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#include "xentoollog.h"
-
-#include <assert.h>
-#include <errno.h>
-#include <limits.h>
-
-static const char *level_strings[XTL_NUM_LEVELS]= {
-    "[BUG:XTL_NONE]",
-    "debug", "verbose", "detail",  /* normally off by default */
-    "progress", "info", "notice",  /* not a problem */
-    "warning", "error", "critical" /* problems and errors */
-};
-
-const char *xtl_level_to_string(xentoollog_level level) {
-    assert(level >= 0 && level < XTL_NUM_LEVELS);
-    return level_strings[level];
-}
-
-void xtl_logv(struct xentoollog_logger *logger,
-              xentoollog_level level,
-              int errnoval /* or -1 */,
-              const char *context /* eg "xc", "xenstore", "xl" */,
-              const char *format /* does not contain \n */,
-              va_list al) {
-    int errno_save = errno;
-    assert(level > XTL_NONE && level < XTL_NUM_LEVELS);
-    logger->vmessage(logger,level,errnoval,context,format,al);
-    errno = errno_save;
-}
-
-void xtl_log(struct xentoollog_logger *logger,
-             xentoollog_level level,
-             int errnoval /* or -1 */,
-             const char *context /* eg "xc", "xenstore", "xl" */,
-             const char *format /* does not contain \n */,
-             ...) {
-    va_list al;
-    va_start(al,format);
-    xtl_logv(logger,level,errnoval,context,format,al);
-    va_end(al);
-}
-
-void xtl_progress(struct xentoollog_logger *logger,
-                  const char *context, const char *doing_what,
-                  unsigned long done, unsigned long total) {
-    int percent = 0;
-
-    if (!logger->progress) return;
-
-    if ( total )
-        percent = (total < LONG_MAX/100)
-            ? (done * 100) / total
-            : done / ((total + 99) / 100);
-
-    logger->progress(logger, context, doing_what, percent, done, total);
-}
-
-void xtl_logger_destroy(struct xentoollog_logger *logger) {
-    if (!logger) return;
-    logger->destroy(logger);
-}
diff --git a/tools/libxc/xtl_logger_stdio.c b/tools/libxc/xtl_logger_stdio.c
deleted file mode 100644
index b28ef73..0000000
--- a/tools/libxc/xtl_logger_stdio.c
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * xtl_logger_stdio.c
- *
- * log message consumer that writes to stdio
- *
- * Copyright (c) 2010 Citrix
- * Part of a generic logging interface used by various dom0 userland libraries.
- *
- * This library 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 of the License.
- *
- * This library 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.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#include "xentoollog.h"
-
-#include <time.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <stdbool.h>
-
-struct xentoollog_logger_stdiostream {
-    xentoollog_logger vtable;
-    FILE *f;
-    xentoollog_level min_level;
-    unsigned flags;
-    int progress_erase_len, progress_last_percent;
-    bool progress_use_cr;
-};
-
-static void progress_erase(xentoollog_logger_stdiostream *lg) {
-    if (lg->progress_erase_len)
-        fprintf(lg->f, "\r%*s\r", lg->progress_erase_len, "");
-}
-
-static void stdiostream_vmessage(xentoollog_logger *logger_in,
-                                 xentoollog_level level,
-                                 int errnoval,
-                                 const char *context,
-                                 const char *format,
-                                 va_list al) {
-    xentoollog_logger_stdiostream *lg = (void*)logger_in;
-
-    if (level < lg->min_level)
-        return;
-
-    progress_erase(lg);
-
-    if (lg->flags & XTL_STDIOSTREAM_SHOW_DATE) {
-        struct tm lt_buf;
-        time_t now = time(0);
-        struct tm *lt= localtime_r(&now, &lt_buf);
-        if (lt != NULL)
-            fprintf(lg->f, "%04d-%02d-%02d %02d:%02d:%02d %s ",
-                    lt->tm_year+1900, lt->tm_mon+1, lt->tm_mday,
-                    lt->tm_hour, lt->tm_min, lt->tm_sec,
-                    tzname[!!lt->tm_isdst]);
-        else
-            fprintf(lg->f, "[localtime_r failed: %d] ", errno);
-    }
-    if (lg->flags & XTL_STDIOSTREAM_SHOW_PID)
-        fprintf(lg->f, "[%lu] ", (unsigned long)getpid());
-
-    if (context)
-        fprintf(lg->f, "%s: ", context);
-
-    fprintf(lg->f, "%s: ", xtl_level_to_string(level));
-
-    vfprintf(lg->f, format, al);
-
-    if (errnoval >= 0)
-        fprintf(lg->f, ": %s", strerror(errnoval));
-
-    putc('\n', lg->f);
-    fflush(lg->f);
-}
-
-static void stdiostream_message(struct xentoollog_logger *logger_in,
-                                xentoollog_level level,
-                                const char *context,
-                                const char *format, ...)
-{
-    va_list al;
-    va_start(al,format);
-    stdiostream_vmessage(logger_in, level, -1, context, format, al);
-    va_end(al);
-}
-
-static void stdiostream_progress(struct xentoollog_logger *logger_in,
-                                 const char *context,
-                                 const char *doing_what, int percent,
-                                 unsigned long done, unsigned long total) {
-    xentoollog_logger_stdiostream *lg = (void*)logger_in;
-    int newpel, extra_erase;
-    xentoollog_level this_level;
-
-    if (lg->flags & XTL_STDIOSTREAM_HIDE_PROGRESS)
-        return;
-
-    if (percent < lg->progress_last_percent) {
-        this_level = XTL_PROGRESS;
-    } else if (percent == lg->progress_last_percent) {
-        return;
-    } else if (percent < lg->progress_last_percent + 5) {
-        this_level = XTL_DETAIL;
-    } else {
-        this_level = XTL_PROGRESS;
-    }
-
-    if (this_level < lg->min_level)
-        return;
-
-    lg->progress_last_percent = percent;
-
-    if (!lg->progress_use_cr) {
-        stdiostream_message(logger_in, this_level, context,
-                            "%s: %lu/%lu  %3d%%",
-                            doing_what, done, total, percent);
-        return;
-    }
-
-    if (lg->progress_erase_len)
-        putc('\r', lg->f);
-
-    newpel = fprintf(lg->f, "%s%s" "%s: %lu/%lu  %3d%%%s",
-                     context?context:"", context?": ":"",
-                     doing_what, done, total, percent,
-		     done == total ? "\n" : "");
-
-    extra_erase = lg->progress_erase_len - newpel;
-    if (extra_erase > 0)
-        fprintf(lg->f, "%*s\r", extra_erase, "");
-
-    lg->progress_erase_len = newpel;
-}
-
-static void stdiostream_destroy(struct xentoollog_logger *logger_in) {
-    xentoollog_logger_stdiostream *lg = (void*)logger_in;
-    progress_erase(lg);
-    free(lg);
-}
-
-void xtl_stdiostream_set_minlevel(xentoollog_logger_stdiostream *lg,
-                                  xentoollog_level min_level) {
-    lg->min_level = min_level;
-}
-
-void xtl_stdiostream_adjust_flags(xentoollog_logger_stdiostream *lg,
-                                  unsigned set_flags, unsigned clear_flags) {
-    unsigned new_flags = (lg->flags & ~clear_flags) | set_flags;
-    if (new_flags & XTL_STDIOSTREAM_HIDE_PROGRESS)
-        progress_erase(lg);
-    lg->flags = new_flags;
-}
-
-xentoollog_logger_stdiostream *xtl_createlogger_stdiostream
-        (FILE *f, xentoollog_level min_level, unsigned flags) {
-    xentoollog_logger_stdiostream newlogger;
-
-    newlogger.f = f;
-    newlogger.min_level = min_level;
-    newlogger.flags = flags;
-
-    switch (flags & (XTL_STDIOSTREAM_PROGRESS_USE_CR |
-                     XTL_STDIOSTREAM_PROGRESS_NO_CR)) {
-    case XTL_STDIOSTREAM_PROGRESS_USE_CR: newlogger.progress_use_cr = 1; break;
-    case XTL_STDIOSTREAM_PROGRESS_NO_CR:  newlogger.progress_use_cr = 0; break;
-    case 0:
-        newlogger.progress_use_cr = isatty(fileno(newlogger.f)) > 0;
-        break;
-    default:
-        errno = EINVAL;
-        return 0;
-    }
-
-    if (newlogger.flags & XTL_STDIOSTREAM_SHOW_DATE) tzset();
-
-    newlogger.progress_erase_len = 0;
-    newlogger.progress_last_percent = 0;
-
-    return XTL_NEW_LOGGER(stdiostream, newlogger);
-}
diff --git a/tools/libxentoollog/Makefile b/tools/libxentoollog/Makefile
new file mode 100644
index 0000000..0c8be13
--- /dev/null
+++ b/tools/libxentoollog/Makefile
@@ -0,0 +1,59 @@
+XEN_ROOT = $(CURDIR)/../..
+include $(XEN_ROOT)/tools/Rules.mk
+
+MAJOR	= 1
+MINOR	= 0
+SHLIB_LDFLAGS += -Wl,--version-script=libxentoollog.map
+
+CFLAGS	+= -Werror -Wmissing-prototypes
+CFLAGS	+= -I./include
+
+SRCS-y	+= xtl_core.c
+SRCS-y	+= xtl_logger_stdio.c
+
+LIB_OBJS := $(patsubst %.c,%.o,$(SRCS-y))
+PIC_OBJS := $(patsubst %.c,%.opic,$(SRCS-y))
+
+LIB := libxentoollog.a
+ifneq ($(nosharedlibs),y)
+LIB += libxentoollog.so
+endif
+
+.PHONY: all
+all: build
+
+.PHONY: build
+build:
+	$(MAKE) libs
+
+.PHONY: libs
+libs: $(LIB)
+
+libxentoollog.a: $(LIB_OBJS)
+	$(AR) rc $@ $^
+
+libxentoollog.so: libxentoollog.so.$(MAJOR)
+	$(SYMLINK_SHLIB) $< $@
+libxentoollog.so.$(MAJOR): libxentoollog.so.$(MAJOR).$(MINOR)
+	$(SYMLINK_SHLIB) $< $@
+
+libxentoollog.so.$(MAJOR).$(MINOR): $(PIC_OBJS) libxentoollog.map
+	$(CC) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxentoollog.so.$(MAJOR) $(SHLIB_LDFLAGS) -o $@ $(PIC_OBJS) $(APPEND_LDFLAGS)
+
+.PHONY: install
+install: build
+	$(INSTALL_DIR) $(DESTDIR)$(libdir)
+	$(INSTALL_DIR) $(DESTDIR)$(includedir)
+	$(INSTALL_SHLIB) libxentoollog.so.$(MAJOR).$(MINOR) $(DESTDIR)$(libdir)
+	$(INSTALL_DATA) libxentoollog.a $(DESTDIR)$(libdir)
+	$(SYMLINK_SHLIB) libxentoollog.so.$(MAJOR).$(MINOR) $(DESTDIR)$(libdir)/libxentoollog.so.$(MAJOR)
+	$(SYMLINK_SHLIB) libxentoollog.so.$(MAJOR) $(DESTDIR)$(libdir)/libxentoollog.so
+	$(INSTALL_DATA) include/xentoollog.h $(DESTDIR)$(includedir)
+
+.PHONY: TAGS
+TAGS:
+	etags -t *.c *.h
+
+.PHONY: clean
+clean:
+	rm -rf *.rpm $(LIB) *~ $(DEPS) $(LIB_OBJS) $(PIC_OBJS)
diff --git a/tools/libxentoollog/include/xentoollog.h b/tools/libxentoollog/include/xentoollog.h
new file mode 100644
index 0000000..85d3da9
--- /dev/null
+++ b/tools/libxentoollog/include/xentoollog.h
@@ -0,0 +1,137 @@
+/*
+ * xentoollog.h
+ *
+ * Copyright (c) 2010 Citrix
+ * Part of a generic logging interface used by various dom0 userland libraries.
+ *
+ * This library 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 of the License.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef XENTOOLLOG_H
+#define XENTOOLLOG_H
+
+#include <stdio.h>
+#include <stdarg.h>
+
+
+/*---------- common declarations and types ----------*/
+
+typedef enum xentoollog_level {
+    XTL_NONE, /* sentinel etc, never used for logging */
+    XTL_DEBUG,
+    XTL_VERBOSE,
+    XTL_DETAIL,
+    XTL_PROGRESS, /* also used for "progress" messages */
+    XTL_INFO,
+    XTL_NOTICE,
+    XTL_WARN,
+    XTL_ERROR,
+    XTL_CRITICAL,
+    XTL_NUM_LEVELS
+} xentoollog_level;
+
+typedef struct xentoollog_logger xentoollog_logger;
+struct xentoollog_logger {
+    void (*vmessage)(struct xentoollog_logger *logger,
+                     xentoollog_level level,
+                     int errnoval /* or -1 */,
+                     const char *context /* eg "xc", "xl", may be 0 */,
+                     const char *format /* without level, context, \n */,
+                     va_list al)
+         __attribute__((format(printf,5,0)));
+    void (*progress)(struct xentoollog_logger *logger,
+                     const char *context /* see above */,
+                     const char *doing_what /* no \r,\n */,
+                     int percent, unsigned long done, unsigned long total)
+         /* null function pointer is ok.
+          * will always be called with done==0 for each new
+          * context/doing_what */;
+    void (*destroy)(struct xentoollog_logger *logger);
+    /* each logger can put its necessary data here */
+};
+
+
+/*---------- facilities for consuming log messages ----------*/
+
+#define XTL_STDIOSTREAM_SHOW_PID            001u
+#define XTL_STDIOSTREAM_SHOW_DATE           002u
+#define XTL_STDIOSTREAM_HIDE_PROGRESS       004u
+#define XTL_STDIOSTREAM_PROGRESS_USE_CR     010u /* default is to */
+#define XTL_STDIOSTREAM_PROGRESS_NO_CR      020u /* use \r to ttys */
+
+typedef struct xentoollog_logger_stdiostream  xentoollog_logger_stdiostream;
+
+xentoollog_logger_stdiostream *xtl_createlogger_stdiostream
+        (FILE *f, xentoollog_level min_level, unsigned flags);
+    /* may return 0 if malloc fails, in which case error was logged */
+    /* destroy on this logger does not close the file */
+
+void xtl_stdiostream_set_minlevel(xentoollog_logger_stdiostream*,
+                                  xentoollog_level min_level);
+void xtl_stdiostream_adjust_flags(xentoollog_logger_stdiostream*,
+                                  unsigned set_flags, unsigned clear_flags);
+  /* if set_flags and clear_flags overlap, set_flags takes precedence */
+
+void xtl_logger_destroy(struct xentoollog_logger *logger /* 0 is ok */);
+
+
+/*---------- facilities for generating log messages ----------*/
+
+void xtl_logv(struct xentoollog_logger *logger,
+              xentoollog_level level,
+              int errnoval /* or -1 */,
+              const char *context /* eg "xc", "xenstore", "xl", may be 0 */,
+              const char *format /* does not contain \n */,
+              va_list) __attribute__((format(printf,5,0)));
+
+void xtl_log(struct xentoollog_logger *logger,
+             xentoollog_level level,
+             int errnoval /* or -1 */,
+             const char *context /* eg "xc", "xenstore", "xl" */,
+             const char *format /* does not contain \n */,
+             ...) __attribute__((format(printf,5,6)));
+
+void xtl_progress(struct xentoollog_logger *logger,
+                  const char *context /* see above, may be 0 */,
+                  const char *doing_what,
+                  unsigned long done, unsigned long total);
+
+
+/*---------- facilities for defining log message consumers ----------*/
+
+const char *xtl_level_to_string(xentoollog_level); /* never fails */
+
+
+#define XTL_NEW_LOGGER(LOGGER,buffer) ({                                \
+    xentoollog_logger_##LOGGER *new_consumer;                           \
+                                                                        \
+    (buffer).vtable.vmessage = LOGGER##_vmessage;                       \
+    (buffer).vtable.progress = LOGGER##_progress;                       \
+    (buffer).vtable.destroy  = LOGGER##_destroy;                        \
+                                                                        \
+    new_consumer = malloc(sizeof(*new_consumer));                       \
+    if (!new_consumer) {                                                \
+        xtl_log((xentoollog_logger*)&buffer,                            \
+                XTL_CRITICAL, errno, "xtl",                             \
+                "failed to allocate memory for new message logger");    \
+    } else {                                                            \
+        *new_consumer = buffer;                                         \
+    }                                                                   \
+                                                                        \
+    new_consumer;                                                       \
+});
+
+
+#endif /* XENTOOLLOG_H */
diff --git a/tools/libxentoollog/libxentoollog.map b/tools/libxentoollog/libxentoollog.map
new file mode 100644
index 0000000..c183cf5
--- /dev/null
+++ b/tools/libxentoollog/libxentoollog.map
@@ -0,0 +1,12 @@
+VERS_1.0 {
+	global:
+		xtl_createlogger_stdiostream;
+		xtl_level_to_string;
+		xtl_log;
+		xtl_logger_destroy;
+		xtl_logv;
+		xtl_progress;
+		xtl_stdiostream_adjust_flags;
+		xtl_stdiostream_set_minlevel;
+	local: *; /* Do not expose anything by default */
+};
diff --git a/tools/libxentoollog/xtl_core.c b/tools/libxentoollog/xtl_core.c
new file mode 100644
index 0000000..73add92
--- /dev/null
+++ b/tools/libxentoollog/xtl_core.c
@@ -0,0 +1,84 @@
+/*
+ * xtl_core.c
+ *
+ * core code including functions for generating log messages
+ *
+ * Copyright (c) 2010 Citrix
+ * Part of a generic logging interface used by various dom0 userland libraries.
+ *
+ * This library 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 of the License.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "xentoollog.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+
+static const char *level_strings[XTL_NUM_LEVELS]= {
+    "[BUG:XTL_NONE]",
+    "debug", "verbose", "detail",  /* normally off by default */
+    "progress", "info", "notice",  /* not a problem */
+    "warning", "error", "critical" /* problems and errors */
+};
+
+const char *xtl_level_to_string(xentoollog_level level) {
+    assert(level >= 0 && level < XTL_NUM_LEVELS);
+    return level_strings[level];
+}
+
+void xtl_logv(struct xentoollog_logger *logger,
+              xentoollog_level level,
+              int errnoval /* or -1 */,
+              const char *context /* eg "xc", "xenstore", "xl" */,
+              const char *format /* does not contain \n */,
+              va_list al) {
+    int errno_save = errno;
+    assert(level > XTL_NONE && level < XTL_NUM_LEVELS);
+    logger->vmessage(logger,level,errnoval,context,format,al);
+    errno = errno_save;
+}
+
+void xtl_log(struct xentoollog_logger *logger,
+             xentoollog_level level,
+             int errnoval /* or -1 */,
+             const char *context /* eg "xc", "xenstore", "xl" */,
+             const char *format /* does not contain \n */,
+             ...) {
+    va_list al;
+    va_start(al,format);
+    xtl_logv(logger,level,errnoval,context,format,al);
+    va_end(al);
+}
+
+void xtl_progress(struct xentoollog_logger *logger,
+                  const char *context, const char *doing_what,
+                  unsigned long done, unsigned long total) {
+    int percent = 0;
+
+    if (!logger->progress) return;
+
+    if ( total )
+        percent = (total < LONG_MAX/100)
+            ? (done * 100) / total
+            : done / ((total + 99) / 100);
+
+    logger->progress(logger, context, doing_what, percent, done, total);
+}
+
+void xtl_logger_destroy(struct xentoollog_logger *logger) {
+    if (!logger) return;
+    logger->destroy(logger);
+}
diff --git a/tools/libxentoollog/xtl_logger_stdio.c b/tools/libxentoollog/xtl_logger_stdio.c
new file mode 100644
index 0000000..b28ef73
--- /dev/null
+++ b/tools/libxentoollog/xtl_logger_stdio.c
@@ -0,0 +1,193 @@
+/*
+ * xtl_logger_stdio.c
+ *
+ * log message consumer that writes to stdio
+ *
+ * Copyright (c) 2010 Citrix
+ * Part of a generic logging interface used by various dom0 userland libraries.
+ *
+ * This library 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 of the License.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "xentoollog.h"
+
+#include <time.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <stdbool.h>
+
+struct xentoollog_logger_stdiostream {
+    xentoollog_logger vtable;
+    FILE *f;
+    xentoollog_level min_level;
+    unsigned flags;
+    int progress_erase_len, progress_last_percent;
+    bool progress_use_cr;
+};
+
+static void progress_erase(xentoollog_logger_stdiostream *lg) {
+    if (lg->progress_erase_len)
+        fprintf(lg->f, "\r%*s\r", lg->progress_erase_len, "");
+}
+
+static void stdiostream_vmessage(xentoollog_logger *logger_in,
+                                 xentoollog_level level,
+                                 int errnoval,
+                                 const char *context,
+                                 const char *format,
+                                 va_list al) {
+    xentoollog_logger_stdiostream *lg = (void*)logger_in;
+
+    if (level < lg->min_level)
+        return;
+
+    progress_erase(lg);
+
+    if (lg->flags & XTL_STDIOSTREAM_SHOW_DATE) {
+        struct tm lt_buf;
+        time_t now = time(0);
+        struct tm *lt= localtime_r(&now, &lt_buf);
+        if (lt != NULL)
+            fprintf(lg->f, "%04d-%02d-%02d %02d:%02d:%02d %s ",
+                    lt->tm_year+1900, lt->tm_mon+1, lt->tm_mday,
+                    lt->tm_hour, lt->tm_min, lt->tm_sec,
+                    tzname[!!lt->tm_isdst]);
+        else
+            fprintf(lg->f, "[localtime_r failed: %d] ", errno);
+    }
+    if (lg->flags & XTL_STDIOSTREAM_SHOW_PID)
+        fprintf(lg->f, "[%lu] ", (unsigned long)getpid());
+
+    if (context)
+        fprintf(lg->f, "%s: ", context);
+
+    fprintf(lg->f, "%s: ", xtl_level_to_string(level));
+
+    vfprintf(lg->f, format, al);
+
+    if (errnoval >= 0)
+        fprintf(lg->f, ": %s", strerror(errnoval));
+
+    putc('\n', lg->f);
+    fflush(lg->f);
+}
+
+static void stdiostream_message(struct xentoollog_logger *logger_in,
+                                xentoollog_level level,
+                                const char *context,
+                                const char *format, ...)
+{
+    va_list al;
+    va_start(al,format);
+    stdiostream_vmessage(logger_in, level, -1, context, format, al);
+    va_end(al);
+}
+
+static void stdiostream_progress(struct xentoollog_logger *logger_in,
+                                 const char *context,
+                                 const char *doing_what, int percent,
+                                 unsigned long done, unsigned long total) {
+    xentoollog_logger_stdiostream *lg = (void*)logger_in;
+    int newpel, extra_erase;
+    xentoollog_level this_level;
+
+    if (lg->flags & XTL_STDIOSTREAM_HIDE_PROGRESS)
+        return;
+
+    if (percent < lg->progress_last_percent) {
+        this_level = XTL_PROGRESS;
+    } else if (percent == lg->progress_last_percent) {
+        return;
+    } else if (percent < lg->progress_last_percent + 5) {
+        this_level = XTL_DETAIL;
+    } else {
+        this_level = XTL_PROGRESS;
+    }
+
+    if (this_level < lg->min_level)
+        return;
+
+    lg->progress_last_percent = percent;
+
+    if (!lg->progress_use_cr) {
+        stdiostream_message(logger_in, this_level, context,
+                            "%s: %lu/%lu  %3d%%",
+                            doing_what, done, total, percent);
+        return;
+    }
+
+    if (lg->progress_erase_len)
+        putc('\r', lg->f);
+
+    newpel = fprintf(lg->f, "%s%s" "%s: %lu/%lu  %3d%%%s",
+                     context?context:"", context?": ":"",
+                     doing_what, done, total, percent,
+		     done == total ? "\n" : "");
+
+    extra_erase = lg->progress_erase_len - newpel;
+    if (extra_erase > 0)
+        fprintf(lg->f, "%*s\r", extra_erase, "");
+
+    lg->progress_erase_len = newpel;
+}
+
+static void stdiostream_destroy(struct xentoollog_logger *logger_in) {
+    xentoollog_logger_stdiostream *lg = (void*)logger_in;
+    progress_erase(lg);
+    free(lg);
+}
+
+void xtl_stdiostream_set_minlevel(xentoollog_logger_stdiostream *lg,
+                                  xentoollog_level min_level) {
+    lg->min_level = min_level;
+}
+
+void xtl_stdiostream_adjust_flags(xentoollog_logger_stdiostream *lg,
+                                  unsigned set_flags, unsigned clear_flags) {
+    unsigned new_flags = (lg->flags & ~clear_flags) | set_flags;
+    if (new_flags & XTL_STDIOSTREAM_HIDE_PROGRESS)
+        progress_erase(lg);
+    lg->flags = new_flags;
+}
+
+xentoollog_logger_stdiostream *xtl_createlogger_stdiostream
+        (FILE *f, xentoollog_level min_level, unsigned flags) {
+    xentoollog_logger_stdiostream newlogger;
+
+    newlogger.f = f;
+    newlogger.min_level = min_level;
+    newlogger.flags = flags;
+
+    switch (flags & (XTL_STDIOSTREAM_PROGRESS_USE_CR |
+                     XTL_STDIOSTREAM_PROGRESS_NO_CR)) {
+    case XTL_STDIOSTREAM_PROGRESS_USE_CR: newlogger.progress_use_cr = 1; break;
+    case XTL_STDIOSTREAM_PROGRESS_NO_CR:  newlogger.progress_use_cr = 0; break;
+    case 0:
+        newlogger.progress_use_cr = isatty(fileno(newlogger.f)) > 0;
+        break;
+    default:
+        errno = EINVAL;
+        return 0;
+    }
+
+    if (newlogger.flags & XTL_STDIOSTREAM_SHOW_DATE) tzset();
+
+    newlogger.progress_erase_len = 0;
+    newlogger.progress_last_percent = 0;
+
+    return XTL_NEW_LOGGER(stdiostream, newlogger);
+}
diff --git a/tools/libxl/Makefile b/tools/libxl/Makefile
index 6e74025..cdf350a 100644
--- a/tools/libxl/Makefile
+++ b/tools/libxl/Makefile
@@ -20,11 +20,12 @@ LIBUUID_LIBS += -luuid
 endif
 
 LIBXL_LIBS =
-LIBXL_LIBS = $(LDLIBS_libxenctrl) $(LDLIBS_libxenguest) $(LDLIBS_libxenstore) $(LDLIBS_libblktapctl) $(PTYFUNCS_LIBS) $(LIBUUID_LIBS)
+LIBXL_LIBS = $(LDLIBS_libxentoollog) $(LDLIBS_libxenctrl) $(LDLIBS_libxenguest) $(LDLIBS_libxenstore) $(LDLIBS_libblktapctl) $(PTYFUNCS_LIBS) $(LIBUUID_LIBS)
 ifeq ($(CONFIG_REMUS_NETBUF),y)
 LIBXL_LIBS += $(LIBNL3_LIBS)
 endif
 
+CFLAGS_LIBXL += $(CFLAGS_libxentoollog)
 CFLAGS_LIBXL += $(CFLAGS_libxenctrl)
 CFLAGS_LIBXL += $(CFLAGS_libxenguest)
 CFLAGS_LIBXL += $(CFLAGS_libxenstore)
@@ -148,7 +149,7 @@ CFLAGS_XL += -Wshadow
 
 XL_OBJS = xl.o xl_cmdimpl.o xl_cmdtable.o xl_sxp.o
 $(XL_OBJS) $(TEST_PROG_OBJS) _libxl.api-for-check: \
-            CFLAGS += $(CFLAGS_libxenctrl) # For xentoollog.h
+            CFLAGS += $(CFLAGS_libxentoollog)
 $(XL_OBJS): CFLAGS += $(CFLAGS_XL)
 $(XL_OBJS): CFLAGS += -include $(XEN_ROOT)/tools/config.h # libxl_json.h needs it.
 
@@ -252,19 +253,19 @@ libxlutil.a: $(LIBXLU_OBJS)
 	$(AR) rcs libxlutil.a $^
 
 xl: $(XL_OBJS) libxlutil.so libxenlight.so
-	$(CC) $(LDFLAGS) -o $@ $(XL_OBJS) libxlutil.so $(LDLIBS_libxenlight) $(LDLIBS_libxenctrl) -lyajl $(APPEND_LDFLAGS)
+	$(CC) $(LDFLAGS) -o $@ $(XL_OBJS) libxlutil.so $(LDLIBS_libxenlight) $(LDLIBS_libxentoollog) -lyajl $(APPEND_LDFLAGS)
 
 xen-init-dom0: $(XEN_INIT_DOM0_OBJS) libxenlight.so
-	$(CC) $(LDFLAGS) -o $@ $(XEN_INIT_DOM0_OBJS) $(LDLIBS_libxenstore) $(LDLIBS_libxenlight) $(LDLIBS_libxenctrl) $(APPEND_LDFLAGS)
+	$(CC) $(LDFLAGS) -o $@ $(XEN_INIT_DOM0_OBJS) $(LDLIBS_libxenstore) $(LDLIBS_libxenlight) $(LDLIBS_libxentoollog) $(APPEND_LDFLAGS)
 
 test_%: test_%.o test_common.o libxlutil.so libxenlight_test.so
-	$(CC) $(LDFLAGS) -o $@ $^ $(filter-out %libxenlight.so, $(LDLIBS_libxenlight)) $(LDLIBS_libxenctrl) -lyajl $(APPEND_LDFLAGS)
+	$(CC) $(LDFLAGS) -o $@ $^ $(filter-out %libxenlight.so, $(LDLIBS_libxenlight)) $(LDLIBS_libxentoollog) -lyajl $(APPEND_LDFLAGS)
 
 libxl-save-helper: $(SAVE_HELPER_OBJS) libxenlight.so
-	$(CC) $(LDFLAGS) -o $@ $(SAVE_HELPER_OBJS) $(LDLIBS_libxenctrl) $(LDLIBS_libxenguest) $(APPEND_LDFLAGS)
+	$(CC) $(LDFLAGS) -o $@ $(SAVE_HELPER_OBJS) $(LDLIBS_libxentoollog) $(LDLIBS_libxenctrl) $(LDLIBS_libxenguest) $(APPEND_LDFLAGS)
 
 testidl: testidl.o libxlutil.so libxenlight.so
-	$(CC) $(LDFLAGS) -o $@ testidl.o libxlutil.so $(LDLIBS_libxenlight) $(LDLIBS_libxenctrl) $(APPEND_LDFLAGS)
+	$(CC) $(LDFLAGS) -o $@ testidl.o libxlutil.so $(LDLIBS_libxenlight) $(LDLIBS_libxentoollog) $(APPEND_LDFLAGS)
 
 $(PKG_CONFIG): % : %.in Makefile
 	@sed -e 's/@@version@@/$(MAJOR).$(MINOR)/g' < $< > $@.new
diff --git a/tools/ocaml/Makefile.rules b/tools/ocaml/Makefile.rules
index 1796060..45e71f2 100644
--- a/tools/ocaml/Makefile.rules
+++ b/tools/ocaml/Makefile.rules
@@ -1,18 +1,18 @@
-ifdef V
-  ifeq ("$(origin V)", "command line")
-    BUILD_VERBOSE = $(V)
-  endif
-endif
-ifndef BUILD_VERBOSE
-  BUILD_VERBOSE = 0
-endif
-ifeq ($(BUILD_VERBOSE),1)
+#ifdef V
+#  ifeq ("$(origin V)", "command line")
+#    BUILD_VERBOSE = $(V)
+#  endif
+#endif
+#ifndef BUILD_VERBOSE
+#  BUILD_VERBOSE = 0
+#endif
+#ifeq ($(BUILD_VERBOSE),1)
   E = @true
   Q =
-else
-  E = @echo
-  Q = @
-endif
+#else
+#  E = @echo
+#  Q = @
+#endif
 
 .NOTPARALLEL:
 
diff --git a/tools/ocaml/libs/xentoollog/Makefile b/tools/ocaml/libs/xentoollog/Makefile
index 666eb66..084a3f4 100644
--- a/tools/ocaml/libs/xentoollog/Makefile
+++ b/tools/ocaml/libs/xentoollog/Makefile
@@ -5,7 +5,7 @@ include $(TOPLEVEL)/common.make
 # allow mixed declarations and code
 CFLAGS += -Wno-declaration-after-statement
 
-CFLAGS += $(CFLAGS_libxenctrl) $(CFLAGS_libxenguest)
+CFLAGS += $(CFLAGS_libxentoollog)
 CFLAGS += $(APPEND_CFLAGS)
 OCAMLINCLUDE +=
 
@@ -13,7 +13,7 @@ OBJS = xentoollog
 INTF = xentoollog.cmi
 LIBS = xentoollog.cma xentoollog.cmxa
 
-LIBS_xentoollog = $(LDLIBS_libxenctrl)
+LIBS_xentoollog = $(LDLIBS_libxentoollog)
 
 xentoollog_OBJS = $(OBJS)
 xentoollog_C_OBJS = xentoollog_stubs
@@ -49,7 +49,7 @@ xentoollog.mli: xentoollog.mli.in _xtl_levels.mli.in
 
 libs: $(LIBS)
 
-_xtl_levels.ml.in _xtl_levels.mli.in _xtl_levels.inc: genlevels.py $(XEN_ROOT)/tools/libxc/include/xentoollog.h
+_xtl_levels.ml.in _xtl_levels.mli.in _xtl_levels.inc: genlevels.py $(XEN_ROOT)/tools/libxentoollog/include/xentoollog.h
 	$(PYTHON) genlevels.py _xtl_levels.mli.in _xtl_levels.ml.in _xtl_levels.inc
 
 .PHONY: install
diff --git a/tools/ocaml/libs/xentoollog/genlevels.py b/tools/ocaml/libs/xentoollog/genlevels.py
index 65d334f..4de4fb1 100755
--- a/tools/ocaml/libs/xentoollog/genlevels.py
+++ b/tools/ocaml/libs/xentoollog/genlevels.py
@@ -3,7 +3,7 @@
 import sys
 
 def read_levels():
-	f = open('../../../libxc/include/xentoollog.h', 'r')
+	f = open('../../../libxentoollog/include/xentoollog.h', 'r')
 
 	levels = []
 	record = False
diff --git a/tools/python/setup.py b/tools/python/setup.py
index 5bf81be..5a03266 100644
--- a/tools/python/setup.py
+++ b/tools/python/setup.py
@@ -7,16 +7,17 @@ XEN_ROOT = "../.."
 extra_compile_args  = [ "-fno-strict-aliasing", "-Werror" ]
 
 PATH_XEN      = XEN_ROOT + "/tools/include"
+PATH_LIBXENTOOLLOG = XEN_ROOT + "/tools/libxentoollog"
 PATH_LIBXC    = XEN_ROOT + "/tools/libxc"
 PATH_LIBXL    = XEN_ROOT + "/tools/libxl"
 PATH_XENSTORE = XEN_ROOT + "/tools/xenstore"
 
 xc = Extension("xc",
                extra_compile_args = extra_compile_args,
-               include_dirs       = [ PATH_XEN, PATH_LIBXC + "/include", "xen/lowlevel/xc" ],
+               include_dirs       = [ PATH_XEN, PATH_LIBXENTOOLLOG + "/include", PATH_LIBXC + "/include", "xen/lowlevel/xc" ],
                library_dirs       = [ PATH_LIBXC ],
                libraries          = [ "xenctrl", "xenguest" ],
-               depends            = [ PATH_LIBXC + "/libxenctrl.so", PATH_LIBXC + "/libxenguest.so" ],
+               depends            = [ PATH_LIBXC + "/libxenctrl.so", PATH_LIBXC + "/libxenguest.so",  "-Wl,-rpath-link="+PATH_LIBXENTOOLLOG ],
                sources            = [ "xen/lowlevel/xc/xc.c" ])
 
 xs = Extension("xs",
diff --git a/tools/xenpaging/Makefile b/tools/xenpaging/Makefile
index 2407a30..e63d894 100644
--- a/tools/xenpaging/Makefile
+++ b/tools/xenpaging/Makefile
@@ -3,7 +3,7 @@ include $(XEN_ROOT)/tools/Rules.mk
 
 # xenpaging.c and file_ops.c incorrectly use libxc internals
 CFLAGS += $(CFLAGS_libxenctrl) $(CFLAGS_libxenstore) $(PTHREAD_CFLAGS) -I$(XEN_ROOT)/tools/libxc
-LDLIBS += $(LDLIBS_libxenctrl) $(LDLIBS_libxenstore) $(PTHREAD_LIBS)
+LDLIBS += $(LDLIBS_libxentoollog) $(LDLIBS_libxenctrl) $(LDLIBS_libxenstore) $(PTHREAD_LIBS)
 LDFLAGS += $(PTHREAD_LDFLAGS)
 
 POLICY    = default
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH XEN v2 04/15] tools/libxc: Remove osdep indirection for xc_evtchn
  2015-07-15 15:46 [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries Ian Campbell
                   ` (2 preceding siblings ...)
  2015-07-15 15:46 ` [PATCH XEN v2 03/15] tools: Refactor "xentoollog" into its own library Ian Campbell
@ 2015-07-15 15:46 ` Ian Campbell
  2015-07-15 15:46 ` [PATCH XEN v2 05/15] tools: Refactor /dev/xen/evtchn wrappers into libxenevtchn Ian Campbell
                   ` (23 subsequent siblings)
  27 siblings, 0 replies; 55+ messages in thread
From: Ian Campbell @ 2015-07-15 15:46 UTC (permalink / raw)
  To: ian.jackson, wei.liu2, xen-devel
  Cc: roger.pau, Ian Campbell, stefano.stabellini

The alternative backend (a xen-api/xapi shim) is no longer around and
so this stuff is now just baggage which is getting in the way of
refactoring libxenctrl.

Note that the intention is to move this into a separate library
shortly.

Nested virt probably suffices for this use case now.

One incorrect instance of using xc_interface where xc_evtchn (in ocaml
stubs) is removed, this used to work because they were typedefs to the
same struct, but is no longer permitted.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
---
 tools/libxc/include/xenctrl.h                 |  2 +-
 tools/libxc/include/xenctrlosdep.h            | 16 -----
 tools/libxc/xc_evtchn.c                       | 45 --------------
 tools/libxc/xc_freebsd_osdep.c                | 79 ++++++++----------------
 tools/libxc/xc_linux_osdep.c                  | 76 +++++++++--------------
 tools/libxc/xc_minios.c                       | 63 ++++++++-----------
 tools/libxc/xc_netbsd.c                       | 72 ++++++++--------------
 tools/libxc/xc_private.c                      | 37 +++++++++---
 tools/libxc/xc_private.h                      | 17 ++++++
 tools/libxc/xc_solaris.c                      | 71 ++++++++--------------
 tools/libxc/xenctrl_osdep_ENOSYS.c            | 87 ---------------------------
 tools/ocaml/libs/eventchn/xeneventchn_stubs.c |  4 +-
 12 files changed, 180 insertions(+), 389 deletions(-)

diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h
index ce9029c..53df9a9 100644
--- a/tools/libxc/include/xenctrl.h
+++ b/tools/libxc/include/xenctrl.h
@@ -118,7 +118,7 @@
  */
 
 typedef struct xc_interface_core xc_interface;
-typedef struct xc_interface_core xc_evtchn;
+typedef struct xenevtchn_handle xc_evtchn;
 typedef struct xc_interface_core xc_gnttab;
 typedef struct xc_interface_core xc_gntshr;
 
diff --git a/tools/libxc/include/xenctrlosdep.h b/tools/libxc/include/xenctrlosdep.h
index e97944b..a8b27ae 100644
--- a/tools/libxc/include/xenctrlosdep.h
+++ b/tools/libxc/include/xenctrlosdep.h
@@ -52,7 +52,6 @@
 
 enum xc_osdep_type {
     XC_OSDEP_PRIVCMD,
-    XC_OSDEP_EVTCHN,
     XC_OSDEP_GNTTAB,
     XC_OSDEP_GNTSHR,
 };
@@ -91,21 +90,6 @@ struct xc_osdep_ops
                                         int nentries);
         } privcmd;
         struct {
-            int (*fd)(xc_evtchn *xce, xc_osdep_handle h);
-
-            int (*notify)(xc_evtchn *xce, xc_osdep_handle h, evtchn_port_t port);
-
-            evtchn_port_or_error_t (*bind_unbound_port)(xc_evtchn *xce, xc_osdep_handle h, int domid);
-            evtchn_port_or_error_t (*bind_interdomain)(xc_evtchn *xce, xc_osdep_handle h, int domid,
-                                                       evtchn_port_t remote_port);
-            evtchn_port_or_error_t (*bind_virq)(xc_evtchn *xce, xc_osdep_handle h, unsigned int virq);
-
-            int (*unbind)(xc_evtchn *xce, xc_osdep_handle h, evtchn_port_t port);
-
-            evtchn_port_or_error_t (*pending)(xc_evtchn *xce, xc_osdep_handle h);
-            int (*unmask)(xc_evtchn *xce, xc_osdep_handle h, evtchn_port_t port);
-        } evtchn;
-        struct {
 #define XC_GRANT_MAP_SINGLE_DOMAIN 0x1
             void *(*grant_map)(xc_gnttab *xcg, xc_osdep_handle h,
                                uint32_t count, int flags, int prot,
diff --git a/tools/libxc/xc_evtchn.c b/tools/libxc/xc_evtchn.c
index 2e0679e..e6bd25c 100644
--- a/tools/libxc/xc_evtchn.c
+++ b/tools/libxc/xc_evtchn.c
@@ -78,51 +78,6 @@ int xc_evtchn_status(xc_interface *xch, xc_evtchn_status_t *status)
                         sizeof(*status), 1);
 }
 
-int xc_evtchn_fd(xc_evtchn *xce)
-{
-    return xce->ops->u.evtchn.fd(xce, xce->ops_handle);
-}
-
-int xc_evtchn_notify(xc_evtchn *xce, evtchn_port_t port)
-{
-    return xce->ops->u.evtchn.notify(xce, xce->ops_handle, port);
-}
-
-evtchn_port_or_error_t
-xc_evtchn_bind_unbound_port(xc_evtchn *xce, int domid)
-{
-    return xce->ops->u.evtchn.bind_unbound_port(xce, xce->ops_handle, domid);
-}
-
-evtchn_port_or_error_t
-xc_evtchn_bind_interdomain(xc_evtchn *xce, int domid,
-                           evtchn_port_t remote_port)
-{
-    return xce->ops->u.evtchn.bind_interdomain(xce, xce->ops_handle, domid, remote_port);
-}
-
-evtchn_port_or_error_t
-xc_evtchn_bind_virq(xc_evtchn *xce, unsigned int virq)
-{
-    return xce->ops->u.evtchn.bind_virq(xce, xce->ops_handle, virq);
-}
-
-int xc_evtchn_unbind(xc_evtchn *xce, evtchn_port_t port)
-{
-    return xce->ops->u.evtchn.unbind(xce, xce->ops_handle, port);
-}
-
-evtchn_port_or_error_t
-xc_evtchn_pending(xc_evtchn *xce)
-{
-    return xce->ops->u.evtchn.pending(xce, xce->ops_handle);
-}
-
-int xc_evtchn_unmask(xc_evtchn *xce, evtchn_port_t port)
-{
-    return xce->ops->u.evtchn.unmask(xce, xce->ops_handle, port);
-}
-
 /*
  * Local variables:
  * mode: C
diff --git a/tools/libxc/xc_freebsd_osdep.c b/tools/libxc/xc_freebsd_osdep.c
index 011112b..09d0693 100644
--- a/tools/libxc/xc_freebsd_osdep.c
+++ b/tools/libxc/xc_freebsd_osdep.c
@@ -253,34 +253,32 @@ static struct xc_osdep_ops freebsd_privcmd_ops = {
 };
 
 /*-------------------------- Evtchn device interface -------------------------*/
-static xc_osdep_handle
-freebsd_evtchn_open(xc_evtchn *xce)
+int osdep_evtchn_open(xc_evtchn *xce)
 {
     int fd = open(EVTCHN_DEV, O_RDWR);
     if ( fd == -1 )
-        return XC_OSDEP_OPEN_ERROR;
-
-    return (xc_osdep_handle)fd;
+        return -1;
+    xce->fd = fd;
+    return 0;
 }
 
-static int
-freebsd_evtchn_close(xc_evtchn *xce, xc_osdep_handle h)
+int osdep_evtchn_close(xc_evtchn *xce)
 {
-    int fd = (int)h;
-    return close(fd);
+    if ( xce->fd == -1 )
+        return 0;
+
+    return close(xce->fd);
 }
 
-static int
-freebsd_evtchn_fd(xc_evtchn *xce, xc_osdep_handle h)
+int xc_evtchn_fd(xc_evtchn *xce)
 {
-    return (int)h;
+    return xce->fd;
 }
 
 /*------------------------------ Evtchn interface ----------------------------*/
-static int
-freebsd_evtchn_notify(xc_evtchn *xce, xc_osdep_handle h, evtchn_port_t port)
+int xc_evtchn_notify(xc_evtchn *xce, evtchn_port_t port)
 {
-    int fd = (int)h;
+    int fd = xce->fd;
     struct ioctl_evtchn_notify notify;
 
     notify.port = port;
@@ -288,10 +286,9 @@ freebsd_evtchn_notify(xc_evtchn *xce, xc_osdep_handle h, evtchn_port_t port)
     return ioctl(fd, IOCTL_EVTCHN_NOTIFY, &notify);
 }
 
-static evtchn_port_or_error_t
-freebsd_evtchn_bind_unbound_port(xc_evtchn *xce, xc_osdep_handle h, int domid)
+evtchn_port_or_error_t xc_evtchn_bind_unbound_port(xc_evtchn *xce, int domid)
 {
-    int ret, fd = (int)h;
+    int ret, fd = xce->fd;
     struct ioctl_evtchn_bind_unbound_port bind;
 
     bind.remote_domain = domid;
@@ -300,11 +297,10 @@ freebsd_evtchn_bind_unbound_port(xc_evtchn *xce, xc_osdep_handle h, int domid)
     return ( ret == 0 ) ? bind.port : ret;
 }
 
-static evtchn_port_or_error_t
-freebsd_evtchn_bind_interdomain(xc_evtchn *xce, xc_osdep_handle h, int domid,
-                                evtchn_port_t remote_port)
+evtchn_port_or_error_t
+xc_evtchn_bind_interdomain(xc_evtchn *xce, int domid, evtchn_port_t remote_port)
 {
-    int ret, fd = (int)h;
+    int ret, fd = xce->fd;
     struct ioctl_evtchn_bind_interdomain bind;
 
     bind.remote_domain = domid;
@@ -314,10 +310,9 @@ freebsd_evtchn_bind_interdomain(xc_evtchn *xce, xc_osdep_handle h, int domid,
     return ( ret == 0 ) ? bind.port : ret;
 }
 
-static evtchn_port_or_error_t
-freebsd_evtchn_bind_virq(xc_evtchn *xce, xc_osdep_handle h, unsigned int virq)
+evtchn_port_or_error_t xc_evtchn_bind_virq(xc_evtchn *xce, unsigned int virq)
 {
-    int ret, fd = (int)h;
+    int ret, fd = xce->fd;
     struct ioctl_evtchn_bind_virq bind;
 
     bind.virq = virq;
@@ -326,10 +321,9 @@ freebsd_evtchn_bind_virq(xc_evtchn *xce, xc_osdep_handle h, unsigned int virq)
     return ( ret == 0 ) ? bind.port : ret;
 }
 
-static int
-freebsd_evtchn_unbind(xc_evtchn *xce, xc_osdep_handle h, evtchn_port_t port)
+int xc_evtchn_unbind(xc_evtchn *xce, evtchn_port_t port)
 {
-    int fd = (int)h;
+    int fd = xce->fd;
     struct ioctl_evtchn_unbind unbind;
 
     unbind.port = port;
@@ -337,10 +331,9 @@ freebsd_evtchn_unbind(xc_evtchn *xce, xc_osdep_handle h, evtchn_port_t port)
     return ioctl(fd, IOCTL_EVTCHN_UNBIND, &unbind);
 }
 
-static evtchn_port_or_error_t
-freebsd_evtchn_pending(xc_evtchn *xce, xc_osdep_handle h)
+evtchn_port_or_error_t xc_evtchn_pending(xc_evtchn *xce)
 {
-    int fd = (int)h;
+    int fd = xce->fd;
     evtchn_port_t port;
 
     if ( read(fd, &port, sizeof(port)) != sizeof(port) )
@@ -349,33 +342,15 @@ freebsd_evtchn_pending(xc_evtchn *xce, xc_osdep_handle h)
     return port;
 }
 
-static int
-freebsd_evtchn_unmask(xc_evtchn *xce, xc_osdep_handle h, evtchn_port_t port)
+int xc_evtchn_unmask(xc_evtchn *xce, evtchn_port_t port)
 {
-    int fd = (int)h;
+    int fd = xce->fd;
 
     if ( write(fd, &port, sizeof(port)) != sizeof(port) )
         return -1;
     return 0;
 }
 
-/*----------------------------- Evtchn handlers ------------------------------*/
-static struct xc_osdep_ops freebsd_evtchn_ops = {
-    .open = &freebsd_evtchn_open,
-    .close = &freebsd_evtchn_close,
-
-    .u.evtchn = {
-        .fd = &freebsd_evtchn_fd,
-        .notify = &freebsd_evtchn_notify,
-        .bind_unbound_port = &freebsd_evtchn_bind_unbound_port,
-        .bind_interdomain = &freebsd_evtchn_bind_interdomain,
-        .bind_virq = &freebsd_evtchn_bind_virq,
-        .unbind = &freebsd_evtchn_unbind,
-        .pending = &freebsd_evtchn_pending,
-        .unmask = &freebsd_evtchn_unmask,
-    },
-};
-
 /*---------------------------- FreeBSD interface -----------------------------*/
 static struct xc_osdep_ops *
 freebsd_osdep_init(xc_interface *xch, enum xc_osdep_type type)
@@ -384,8 +359,6 @@ freebsd_osdep_init(xc_interface *xch, enum xc_osdep_type type)
     {
     case XC_OSDEP_PRIVCMD:
         return &freebsd_privcmd_ops;
-    case XC_OSDEP_EVTCHN:
-        return &freebsd_evtchn_ops;
     default:
         return NULL;
     }
diff --git a/tools/libxc/xc_linux_osdep.c b/tools/libxc/xc_linux_osdep.c
index 2687424..3c96c76 100644
--- a/tools/libxc/xc_linux_osdep.c
+++ b/tools/libxc/xc_linux_osdep.c
@@ -39,10 +39,9 @@
 #include "xenctrl.h"
 #include "xenctrlosdep.h"
 
+#include "xc_private.h"
+
 #define ROUNDUP(_x,_w) (((unsigned long)(_x)+(1UL<<(_w))-1) & ~((1UL<<(_w))-1))
-#define ERROR(_m, _a...)  xc_osdep_log(xch,XTL_ERROR,XC_INTERNAL_ERROR,_m , ## _a )
-#define PERROR(_m, _a...) xc_osdep_log(xch,XTL_ERROR,XC_INTERNAL_ERROR,_m \
-                  " (%d = %s)", ## _a , errno, xc_strerror(xch, errno))
 
 static xc_osdep_handle linux_privcmd_open(xc_interface *xch)
 {
@@ -457,29 +456,31 @@ static struct xc_osdep_ops linux_privcmd_ops = {
 
 #define DEVXEN "/dev/xen/"
 
-static xc_osdep_handle linux_evtchn_open(xc_evtchn *xce)
+int osdep_evtchn_open(xc_evtchn *xce)
 {
     int fd = open(DEVXEN "evtchn", O_RDWR);
     if ( fd == -1 )
-        return XC_OSDEP_OPEN_ERROR;
-
-    return (xc_osdep_handle)fd;
+        return -1;
+    xce->fd = fd;
+    return 0;
 }
 
-static int linux_evtchn_close(xc_evtchn *xce, xc_osdep_handle h)
+int osdep_evtchn_close(xc_evtchn *xce)
 {
-    int fd = (int)h;
-    return close(fd);
+    if ( xce->fd == -1 )
+        return 0;
+
+    return close(xce->fd);
 }
 
-static int linux_evtchn_fd(xc_evtchn *xce, xc_osdep_handle h)
+int xc_evtchn_fd(xc_evtchn *xce)
 {
-    return (int)h;
+    return xce->fd;
 }
 
-static int linux_evtchn_notify(xc_evtchn *xce, xc_osdep_handle h, evtchn_port_t port)
+int xc_evtchn_notify(xc_evtchn *xce, evtchn_port_t port)
 {
-    int fd = (int)h;
+    int fd = xce->fd;
     struct ioctl_evtchn_notify notify;
 
     notify.port = port;
@@ -487,10 +488,9 @@ static int linux_evtchn_notify(xc_evtchn *xce, xc_osdep_handle h, evtchn_port_t
     return ioctl(fd, IOCTL_EVTCHN_NOTIFY, &notify);
 }
 
-static evtchn_port_or_error_t
-linux_evtchn_bind_unbound_port(xc_evtchn *xce, xc_osdep_handle h, int domid)
+evtchn_port_or_error_t xc_evtchn_bind_unbound_port(xc_evtchn *xce, int domid)
 {
-    int fd = (int)h;
+    int fd = xce->fd;
     struct ioctl_evtchn_bind_unbound_port bind;
 
     bind.remote_domain = domid;
@@ -498,11 +498,10 @@ linux_evtchn_bind_unbound_port(xc_evtchn *xce, xc_osdep_handle h, int domid)
     return ioctl(fd, IOCTL_EVTCHN_BIND_UNBOUND_PORT, &bind);
 }
 
-static evtchn_port_or_error_t
-linux_evtchn_bind_interdomain(xc_evtchn *xce, xc_osdep_handle h, int domid,
-                              evtchn_port_t remote_port)
+evtchn_port_or_error_t xc_evtchn_bind_interdomain(xc_evtchn *xce, int domid,
+                                                  evtchn_port_t remote_port)
 {
-    int fd = (int)h;
+    int fd = xce->fd;
     struct ioctl_evtchn_bind_interdomain bind;
 
     bind.remote_domain = domid;
@@ -511,10 +510,9 @@ linux_evtchn_bind_interdomain(xc_evtchn *xce, xc_osdep_handle h, int domid,
     return ioctl(fd, IOCTL_EVTCHN_BIND_INTERDOMAIN, &bind);
 }
 
-static evtchn_port_or_error_t
-linux_evtchn_bind_virq(xc_evtchn *xce, xc_osdep_handle h, unsigned int virq)
+evtchn_port_or_error_t xc_evtchn_bind_virq(xc_evtchn *xce, unsigned int virq)
 {
-    int fd = (int)h;
+    int fd = xce->fd;
     struct ioctl_evtchn_bind_virq bind;
 
     bind.virq = virq;
@@ -522,9 +520,9 @@ linux_evtchn_bind_virq(xc_evtchn *xce, xc_osdep_handle h, unsigned int virq)
     return ioctl(fd, IOCTL_EVTCHN_BIND_VIRQ, &bind);
 }
 
-static int linux_evtchn_unbind(xc_evtchn *xce, xc_osdep_handle h, evtchn_port_t port)
+int xc_evtchn_unbind(xc_evtchn *xce, evtchn_port_t port)
 {
-    int fd = (int)h;
+    int fd = xce->fd;
     struct ioctl_evtchn_unbind unbind;
 
     unbind.port = port;
@@ -532,9 +530,9 @@ static int linux_evtchn_unbind(xc_evtchn *xce, xc_osdep_handle h, evtchn_port_t
     return ioctl(fd, IOCTL_EVTCHN_UNBIND, &unbind);
 }
 
-static evtchn_port_or_error_t linux_evtchn_pending(xc_evtchn *xce, xc_osdep_handle h)
+evtchn_port_or_error_t xc_evtchn_pending(xc_evtchn *xce)
 {
-    int fd = (int)h;
+    int fd = xce->fd;
     evtchn_port_t port;
 
     if ( read(fd, &port, sizeof(port)) != sizeof(port) )
@@ -543,31 +541,15 @@ static evtchn_port_or_error_t linux_evtchn_pending(xc_evtchn *xce, xc_osdep_hand
     return port;
 }
 
-static int linux_evtchn_unmask(xc_evtchn *xce, xc_osdep_handle h, evtchn_port_t port)
+int xc_evtchn_unmask(xc_evtchn *xce, evtchn_port_t port)
 {
-    int fd = (int)h;
+    int fd = xce->fd;
 
     if ( write(fd, &port, sizeof(port)) != sizeof(port) )
         return -1;
     return 0;
 }
 
-static struct xc_osdep_ops linux_evtchn_ops = {
-    .open = &linux_evtchn_open,
-    .close = &linux_evtchn_close,
-
-    .u.evtchn = {
-        .fd = &linux_evtchn_fd,
-        .notify = &linux_evtchn_notify,
-        .bind_unbound_port = &linux_evtchn_bind_unbound_port,
-        .bind_interdomain = &linux_evtchn_bind_interdomain,
-        .bind_virq = &linux_evtchn_bind_virq,
-        .unbind = &linux_evtchn_unbind,
-        .pending = &linux_evtchn_pending,
-        .unmask = &linux_evtchn_unmask,
-    },
-};
-
 static xc_osdep_handle linux_gnttab_open(xc_gnttab *xcg)
 {
     int fd = open(DEVXEN "gntdev", O_RDWR);
@@ -871,8 +853,6 @@ static struct xc_osdep_ops *linux_osdep_init(xc_interface *xch, enum xc_osdep_ty
     {
     case XC_OSDEP_PRIVCMD:
         return &linux_privcmd_ops;
-    case XC_OSDEP_EVTCHN:
-        return &linux_evtchn_ops;
     case XC_OSDEP_GNTTAB:
         return &linux_gnttab_ops;
     case XC_OSDEP_GNTSHR:
diff --git a/tools/libxc/xc_minios.c b/tools/libxc/xc_minios.c
index e703684..e9c4d8b 100644
--- a/tools/libxc/xc_minios.c
+++ b/tools/libxc/xc_minios.c
@@ -220,20 +220,23 @@ static void port_dealloc(struct evtchn_port_info *port_info) {
     free(port_info);
 }
 
-static xc_osdep_handle minios_evtchn_open(xc_evtchn *xce)
+int osdep_evtchn_open(xc_evtchn *xce)
 {
     int fd = alloc_fd(FTYPE_EVTCHN);
     if ( fd == -1 )
-        return XC_OSDEP_OPEN_ERROR;
+        return -1;
     LIST_INIT(&files[fd].evtchn.ports);
+    xce->fd = fd;
     printf("evtchn_open() -> %d\n", fd);
-    return (xc_osdep_handle)fd;
+    return 0;
 }
 
-static int minios_evtchn_close(xc_evtchn *xce, xc_osdep_handle h)
+int osdep_evtchn_close(xc_evtchn *xce, xc_osdep_handle h)
 {
-    int fd = (int)h;
-    return close(fd);
+    if ( xce->fd == -1 )
+        return 0;
+
+    return close(xce->fd);
 }
 
 void minios_evtchn_close_fd(int fd)
@@ -245,12 +248,12 @@ void minios_evtchn_close_fd(int fd)
     files[fd].type = FTYPE_NONE;
 }
 
-static int minios_evtchn_fd(xc_evtchn *xce, xc_osdep_handle h)
+int xc_evtchn_fd(xc_evtchn *xce)
 {
-    return (int)h;
+    return xce->fd;
 }
 
-static int minios_evtchn_notify(xc_evtchn *xce, xc_osdep_handle h, evtchn_port_t port)
+int xc_evtchn_notify(xc_evtchn *xce, evtchn_port_t port)
 {
     int ret;
 
@@ -282,9 +285,9 @@ static void evtchn_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
     wake_up(&event_queue);
 }
 
-static evtchn_port_or_error_t minios_evtchn_bind_unbound_port(xc_evtchn *xce, xc_osdep_handle h, int domid)
+evtchn_port_or_error_t xc_evtchn_bind_unbound_port(xc_evtchn *xce, int domid)
 {
-    int fd = (int)h;
+    int fd = xce->fd;
     struct evtchn_port_info *port_info;
     int ret;
     evtchn_port_t port;
@@ -309,10 +312,10 @@ static evtchn_port_or_error_t minios_evtchn_bind_unbound_port(xc_evtchn *xce, xc
     return port;
 }
 
-static evtchn_port_or_error_t minios_evtchn_bind_interdomain(xc_evtchn *xce, xc_osdep_handle h, int domid,
-    evtchn_port_t remote_port)
+evtchn_port_or_error_t xc_evtchn_bind_interdomain(xc_evtchn *xce, int domid,
+                                                  evtchn_port_t remote_port)
 {
-    int fd = (int)h;
+    int fd = xce->fd;
     struct evtchn_port_info *port_info;
     evtchn_port_t local_port;
     int ret;
@@ -337,9 +340,9 @@ static evtchn_port_or_error_t minios_evtchn_bind_interdomain(xc_evtchn *xce, xc_
     return local_port;
 }
 
-static int minios_evtchn_unbind(xc_evtchn *xce, xc_osdep_handle h, evtchn_port_t port)
+int xc_evtchn_unbind(xc_evtchn *xce, evtchn_port_t port)
 {
-    int fd = (int)h;
+    int fd = xce->fd;
     struct evtchn_port_info *port_info;
 
     LIST_FOREACH(port_info, &files[fd].evtchn.ports, list) {
@@ -353,9 +356,9 @@ static int minios_evtchn_unbind(xc_evtchn *xce, xc_osdep_handle h, evtchn_port_t
     return -1;
 }
 
-static evtchn_port_or_error_t minios_evtchn_bind_virq(xc_evtchn *xce, xc_osdep_handle h, unsigned int virq)
+evtchn_port_or_error_t xc_evtchn_bind_virq(xc_evtchn *xce, unsigned int virq)
 {
-    int fd = (int)h;
+    int fd = xce->fd;
     struct evtchn_port_info *port_info;
     evtchn_port_t port;
 
@@ -378,9 +381,9 @@ static evtchn_port_or_error_t minios_evtchn_bind_virq(xc_evtchn *xce, xc_osdep_h
     return port;
 }
 
-static evtchn_port_or_error_t minios_evtchn_pending(xc_evtchn *xce, xc_osdep_handle h)
+evtchn_port_or_error_t xc_evtchn_pending(xc_evtchn *xce)
 {
-    int fd = (int)h;
+    int fd = xce->fd;
     struct evtchn_port_info *port_info;
     unsigned long flags;
     evtchn_port_t ret = -1;
@@ -403,28 +406,12 @@ static evtchn_port_or_error_t minios_evtchn_pending(xc_evtchn *xce, xc_osdep_han
     return ret;
 }
 
-static int minios_evtchn_unmask(xc_evtchn *xce, xc_osdep_handle h, evtchn_port_t port)
+int xc_evtchn_unmask(xc_evtchn *xce, evtchn_port_t port)
 {
     unmask_evtchn(port);
     return 0;
 }
 
-static struct xc_osdep_ops minios_evtchn_ops = {
-    .open = &minios_evtchn_open,
-    .close = &minios_evtchn_close,
-
-    .u.evtchn = {
-        .fd = &minios_evtchn_fd,
-        .notify = &minios_evtchn_notify,
-        .bind_unbound_port = &minios_evtchn_bind_unbound_port,
-        .bind_interdomain = &minios_evtchn_bind_interdomain,
-        .bind_virq = &minios_evtchn_bind_virq,
-        .unbind = &minios_evtchn_unbind,
-        .pending = &minios_evtchn_pending,
-        .unmask = &minios_evtchn_unmask,
-   },
-};
-
 /* Optionally flush file to disk and discard page cache */
 void discard_file_cache(xc_interface *xch, int fd, int flush)
 {
@@ -524,8 +511,6 @@ static struct xc_osdep_ops *minios_osdep_init(xc_interface *xch, enum xc_osdep_t
     {
     case XC_OSDEP_PRIVCMD:
         return &minios_privcmd_ops;
-    case XC_OSDEP_EVTCHN:
-        return &minios_evtchn_ops;
     case XC_OSDEP_GNTTAB:
         return &minios_gnttab_ops;
     default:
diff --git a/tools/libxc/xc_netbsd.c b/tools/libxc/xc_netbsd.c
index 8a90ef3..f9bc100 100644
--- a/tools/libxc/xc_netbsd.c
+++ b/tools/libxc/xc_netbsd.c
@@ -226,29 +226,31 @@ static struct xc_osdep_ops netbsd_privcmd_ops = {
 
 #define EVTCHN_DEV_NAME  "/dev/xenevt"
 
-static xc_osdep_handle netbsd_evtchn_open(xc_evtchn *xce)
+int osdep_evtchn_open(xc_evtchn *xce)
 {
     int fd = open(EVTCHN_DEV_NAME, O_NONBLOCK|O_RDWR);
     if ( fd == -1 )
-        return XC_OSDEP_OPEN_ERROR;
-
-    return (xc_osdep_handle)fd;
+        return -1;
+    xce->fd = fd;
+    return 0;
 }
 
-static int netbsd_evtchn_close(xc_evtchn *xce, xc_osdep_handle h)
+int osdep_evtchn_close(xc_evtchn *xce, xc_osdep_handle h)
 {
-    int fd = (int)h;
-    return close(fd);
+    if ( xce->fd == -1 )
+        return 0;
+
+    return close(xce->fd);
 }
 
-static int netbsd_evtchn_fd(xc_evtchn *xce, xc_osdep_handle h)
+int xc_evtchn_fd(xc_evtchn *xce)
 {
-    return (int)h;
+    return xce->fd;
 }
 
-static int netbsd_evtchn_notify(xc_evtchn *xce, xc_osdep_handle h, evtchn_port_t port)
+int xc_evtchn_notify(xc_evtchn *xce, evtchn_port_t port)
 {
-    int fd = (int)h;
+    int fd = xce->fd;
     struct ioctl_evtchn_notify notify;
 
     notify.port = port;
@@ -256,10 +258,9 @@ static int netbsd_evtchn_notify(xc_evtchn *xce, xc_osdep_handle h, evtchn_port_t
     return ioctl(fd, IOCTL_EVTCHN_NOTIFY, &notify);
 }
 
-static evtchn_port_or_error_t
-netbsd_evtchn_bind_unbound_port(xc_evtchn * xce, xc_osdep_handle h, int domid)
+evtchn_port_or_error_t xc_evtchn_bind_unbound_port(xc_evtchn * xce, int domid)
 {
-    int fd = (int)h;
+    int fd = xce->fd;
     struct ioctl_evtchn_bind_unbound_port bind;
     int ret;
 
@@ -272,11 +273,10 @@ netbsd_evtchn_bind_unbound_port(xc_evtchn * xce, xc_osdep_handle h, int domid)
 	return -1;
 }
 
-static evtchn_port_or_error_t
-netbsd_evtchn_bind_interdomain(xc_evtchn *xce, xc_osdep_handle h, int domid,
-                               evtchn_port_t remote_port)
+evtchn_port_or_error_t xc_evtchn_bind_interdomain(xc_evtchn *xce, int domid,
+                                                  evtchn_port_t remote_port)
 {
-    int fd = (int)h;
+    int fd = xce->fd;
     struct ioctl_evtchn_bind_interdomain bind;
     int ret;
 
@@ -290,9 +290,9 @@ netbsd_evtchn_bind_interdomain(xc_evtchn *xce, xc_osdep_handle h, int domid,
 	return -1;
 }
 
-static int netbsd_evtchn_unbind(xc_evtchn *xce, xc_osdep_handle h, evtchn_port_t port)
+int xc_evtchn_unbind(xc_evtchn *xce, evtchn_port_t port)
 {
-    int fd = (int)h;
+    int fd = xce->fd;
     struct ioctl_evtchn_unbind unbind;
 
     unbind.port = port;
@@ -300,10 +300,9 @@ static int netbsd_evtchn_unbind(xc_evtchn *xce, xc_osdep_handle h, evtchn_port_t
     return ioctl(fd, IOCTL_EVTCHN_UNBIND, &unbind);
 }
 
-static evtchn_port_or_error_t
-netbsd_evtchn_bind_virq(xc_evtchn *xce, xc_osdep_handle h, unsigned int virq)
+evtchn_port_or_error_t xc_evtchn_bind_virq(xc_evtchn *xce, unsigned int virq)
 {
-    int fd = (int)h;
+    int fd = xce->fd;
     struct ioctl_evtchn_bind_virq bind;
     int err;
 
@@ -316,10 +315,9 @@ netbsd_evtchn_bind_virq(xc_evtchn *xce, xc_osdep_handle h, unsigned int virq)
 	return bind.port;
 }
 
-static evtchn_port_or_error_t
-netbsd_evtchn_pending(xc_evtchn *xce, xc_osdep_handle h)
+evtchn_port_or_error_t xc_evtchn_pending(xc_evtchn *xce)
 {
-    int fd = (int)h;
+    int fd = xce->fd;
     evtchn_port_t port;
 
     if ( read_exact(fd, (char *)&port, sizeof(port)) == -1 )
@@ -328,28 +326,12 @@ netbsd_evtchn_pending(xc_evtchn *xce, xc_osdep_handle h)
     return port;
 }
 
-static int netbsd_evtchn_unmask(xc_evtchn *xce, xc_osdep_handle h, evtchn_port_t port)
+int xc_evtchn_unmask(xc_evtchn *xce, evtchn_port_t port)
 {
-    int fd = (int)h;
+    int fd = xce->fd;
     return write_exact(fd, (char *)&port, sizeof(port));
 }
 
-static struct xc_osdep_ops netbsd_evtchn_ops = {
-    .open = &netbsd_evtchn_open,
-    .close = &netbsd_evtchn_close,
-
-    .u.evtchn = {
-         .fd = &netbsd_evtchn_fd,
-         .notify = &netbsd_evtchn_notify,
-         .bind_unbound_port = &netbsd_evtchn_bind_unbound_port,
-         .bind_interdomain = &netbsd_evtchn_bind_interdomain,
-         .bind_virq = &netbsd_evtchn_bind_virq,
-         .unbind = &netbsd_evtchn_unbind,
-         .pending = &netbsd_evtchn_pending,
-         .unmask = &netbsd_evtchn_unmask,
-    },
-};
-
 /* Optionally flush file to disk and discard page cache */
 void discard_file_cache(xc_interface *xch, int fd, int flush) 
 {
@@ -396,8 +378,6 @@ static struct xc_osdep_ops *netbsd_osdep_init(xc_interface *xch, enum xc_osdep_t
     {
     case XC_OSDEP_PRIVCMD:
         return &netbsd_privcmd_ops;
-    case XC_OSDEP_EVTCHN:
-        return &netbsd_evtchn_ops;
     default:
         return NULL;
     }
diff --git a/tools/libxc/xc_private.c b/tools/libxc/xc_private.c
index 2ffebd9..9f0ada7 100644
--- a/tools/libxc/xc_private.c
+++ b/tools/libxc/xc_private.c
@@ -120,7 +120,6 @@ static const char *xc_osdep_type_name(enum xc_osdep_type type)
     switch ( type )
     {
     case XC_OSDEP_PRIVCMD: return "privcmd";
-    case XC_OSDEP_EVTCHN:  return "evtchn";
     case XC_OSDEP_GNTTAB:  return "gnttab";
     case XC_OSDEP_GNTSHR:  return "gntshr";
     }
@@ -253,20 +252,44 @@ int do_xen_hypercall(xc_interface *xch, privcmd_hypercall_t *hypercall)
     return xch->ops->u.privcmd.hypercall(xch, xch->ops_handle, hypercall);
 }
 
-xc_evtchn *xc_evtchn_open(xentoollog_logger *logger,
-                             unsigned open_flags)
+xc_evtchn *xc_evtchn_open(xentoollog_logger *logger, unsigned open_flags)
 {
-    xc_evtchn *xce;
+    xc_evtchn *xce = malloc(sizeof(*xce));
+    int rc;
+
+    if (!xce) return NULL;
+
+    xce->fd = -1;
+    xce->logger = logger;
+    xce->logger_tofree  = NULL;
 
-    xce = xc_interface_open_common(logger, NULL, open_flags,
-                                   XC_OSDEP_EVTCHN);
+    if (!xce->logger) {
+        xce->logger = xce->logger_tofree =
+            (xentoollog_logger*)
+            xtl_createlogger_stdiostream(stderr, XTL_PROGRESS, 0);
+        if (!xce->logger) goto err;
+    }
+
+    rc = osdep_evtchn_open(xce);
+    if ( rc  < 0 ) goto err;
 
     return xce;
+
+err:
+    osdep_evtchn_close(xce);
+    xtl_logger_destroy(xce->logger_tofree);
+    free(xce);
+    return NULL;
 }
 
 int xc_evtchn_close(xc_evtchn *xce)
 {
-    return xc_interface_close_common(xce);
+    int rc;
+
+    rc = osdep_evtchn_close(xce);
+    xtl_logger_destroy(xce->logger_tofree);
+    free(xce);
+    return rc;
 }
 
 xc_gnttab *xc_gnttab_open(xentoollog_logger *logger,
diff --git a/tools/libxc/xc_private.h b/tools/libxc/xc_private.h
index 247a408..4c66766 100644
--- a/tools/libxc/xc_private.h
+++ b/tools/libxc/xc_private.h
@@ -124,6 +124,13 @@ struct xc_interface_core {
     xc_osdep_handle  ops_handle; /* opaque data for xc_osdep_ops */
 };
 
+struct xenevtchn_handle {
+    xentoollog_logger *logger, *logger_tofree;
+    int fd;
+};
+int osdep_evtchn_open(xc_evtchn *xce);
+int osdep_evtchn_close(xc_evtchn *xce);
+
 void xc_report_error(xc_interface *xch, int code, const char *fmt, ...)
     __attribute__((format(printf,3,4)));
 void xc_reportv(xc_interface *xch, xentoollog_logger *lg, xentoollog_level,
@@ -447,3 +454,13 @@ void *xc_vm_event_enable(xc_interface *xch, domid_t domain_id, int param,
                          uint32_t *port);
 
 #endif /* __XC_PRIVATE_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxc/xc_solaris.c b/tools/libxc/xc_solaris.c
index 7257a54..8867d97 100644
--- a/tools/libxc/xc_solaris.c
+++ b/tools/libxc/xc_solaris.c
@@ -195,33 +195,36 @@ static struct xc_osdep_ops solaris_privcmd_ops = {
     },
 };
 
-static xc_osdep_handle solaris_evtchn_open(xc_evtchn *xce)
+int osdep_evtchn_open(xc_evtchn *xce)
 {
     int fd;
 
     if ( (fd = open("/dev/xen/evtchn", O_RDWR)) == -1 )
     {
         PERROR("Could not open event channel interface");
-        return XC_OSDEP_OPEN_ERROR;
+        return -1;
     }
 
-    return (xc_osdep_handle)fd;
+    xce->fd = fd;
+    return 0;
 }
 
-static int solaris_evtchn_close(xc_evtchn *xce, xc_osdep_handle h)
+int osdep_evtchn_close(xc_evtchn *xce)
 {
-    int fd = (int)h;
-    return close(fd);
+    if ( xce->fd == -1 )
+        return 0;
+
+    return close(xce->fd);
 }
 
-static int solaris_evtchn_fd(xc_evtchn *xce, xc_osdep_handle h)
+int xc_evtchn_fd(xc_evtchn *xce)
 {
-    return (int)h;
+    return xce->fd;
 }
 
-static int solaris_evtchn_notify(xc_evtchn *xce, xc_osdep_handle h, evtchn_port_t port)
+int xc_evtchn_notify(xc_evtchn *xce, evtchn_port_t port)
 {
-    int fd = (int)h;
+    int fd = xce->fd;
     struct ioctl_evtchn_notify notify;
 
     notify.port = port;
@@ -229,10 +232,9 @@ static int solaris_evtchn_notify(xc_evtchn *xce, xc_osdep_handle h, evtchn_port_
     return ioctl(fd, IOCTL_EVTCHN_NOTIFY, &notify);
 }
 
-static evtchn_port_or_error_t
-solaris_evtchn_bind_unbound_port(xc_evtchn *xce, xc_osdep_handle h, int domid)
+evtchn_port_or_error_t xc_evtchn_bind_unbound_port(xc_evtchn *xce, int domid)
 {
-    int fd = (int)h;
+    int fd = xce->fd;
     struct ioctl_evtchn_bind_unbound_port bind;
 
     bind.remote_domain = domid;
@@ -240,11 +242,10 @@ solaris_evtchn_bind_unbound_port(xc_evtchn *xce, xc_osdep_handle h, int domid)
     return ioctl(fd, IOCTL_EVTCHN_BIND_UNBOUND_PORT, &bind);
 }
 
-evtchn_port_or_error_t
-solaris_evtchn_bind_interdomain(xc_evtchn *xce, xc_osdep_handle h, int domid,
-                           evtchn_port_t remote_port)
+evtchn_port_or_error_t xc_evtchn_bind_interdomain(xc_evtchn *xce, int domid,
+                                                  evtchn_port_t remote_port)
 {
-    int fd = (int)h;
+    int fd = xce->fd;
     struct ioctl_evtchn_bind_interdomain bind;
 
     bind.remote_domain = domid;
@@ -253,10 +254,9 @@ solaris_evtchn_bind_interdomain(xc_evtchn *xce, xc_osdep_handle h, int domid,
     return ioctl(fd, IOCTL_EVTCHN_BIND_INTERDOMAIN, &bind);
 }
 
-static evtchn_port_or_error_t
-solaris_evtchn_bind_virq(xc_evtchn *xce, xc_osdep_handle h, unsigned int virq)
+evtchn_port_or_error_t xc_evtchn_bind_virq(xc_evtchn *xce, unsigned int virq)
 {
-    int fd = (int)h;
+    int fd = xce->fd;
     struct ioctl_evtchn_bind_virq bind;
 
     bind.virq = virq;
@@ -264,9 +264,9 @@ solaris_evtchn_bind_virq(xc_evtchn *xce, xc_osdep_handle h, unsigned int virq)
     return ioctl(fd, IOCTL_EVTCHN_BIND_VIRQ, &bind);
 }
 
-static int solaris_evtchn_unbind(xc_evtchn *xce, xc_osdep_handle h, evtchn_port_t port)
+int xc_evtchn_unbind(xc_evtchn *xce, evtchn_port_t port)
 {
-    int fd = (int)h;
+    int fd = xce->fd;
     struct ioctl_evtchn_unbind unbind;
 
     unbind.port = port;
@@ -274,10 +274,9 @@ static int solaris_evtchn_unbind(xc_evtchn *xce, xc_osdep_handle h, evtchn_port_
     return ioctl(fd, IOCTL_EVTCHN_UNBIND, &unbind);
 }
 
-static evtchn_port_or_error_t
-solaris_evtchn_pending(xc_evtchn *xce, xc_osdep_handle h)
+evtchn_port_or_error_t xc_evtchn_pending(xc_evtchn *xce)
 {
-    int fd = (int)h;
+    int fd = xce->fd;
     evtchn_port_t port;
 
     if ( read_exact(fd, (char *)&port, sizeof(port)) == -1 )
@@ -286,28 +285,12 @@ solaris_evtchn_pending(xc_evtchn *xce, xc_osdep_handle h)
     return port;
 }
 
-static int solaris_evtchn_unmask(xc_evtchn *xce, xc_osdep_handle h,evtchn_port_t port)
+int xc_evtchn_unmask(xc_evtchn *xce, evtchn_port_t port)
 {
-    int fd = (int)h;
+    int fd = xce->fd;
     return write_exact(fd, (char *)&port, sizeof(port));
 }
 
-static struct xc_osdep_ops solaris_evtchn_ops = {
-    .open = &solaris_evtchn_open,
-    .close = &solaris_evtchn_close,
-
-    .u.evtchn = {
-        .fd = &solaris_evtchn_fd,
-        .notify = &solaris_evtchn_notify,
-        .bind_unbound_port = &solaris_evtchn_bind_unbound_port,
-        .bind_interdomain = &solaris_evtchn_bind_interdomain,
-        .bind_virq = &solaris_evtchn_bind_virq,
-        .unbind = &solaris_evtchn_unbind,
-        .pending = &solaris_evtchn_pending,
-        .unmask = &solaris_evtchn_unmask,
-    },
-};
-
 /* Optionally flush file to disk and discard page cache */
 void discard_file_cache(xc_interface *xch, int fd, int flush) 
 {
@@ -325,8 +308,6 @@ static struct xc_osdep_ops *solaris_osdep_init(xc_interface *xch, enum xc_osdep_
     {
     case XC_OSDEP_PRIVCMD:
         return &solaris_privcmd_ops;
-    case XC_OSDEP_EVTCHN:
-        return &solaris_evtchn_ops;
     default:
         return NULL;
     }
diff --git a/tools/libxc/xenctrl_osdep_ENOSYS.c b/tools/libxc/xenctrl_osdep_ENOSYS.c
index dd59dcd..5182532 100644
--- a/tools/libxc/xenctrl_osdep_ENOSYS.c
+++ b/tools/libxc/xenctrl_osdep_ENOSYS.c
@@ -81,90 +81,6 @@ static struct xc_osdep_ops ENOSYS_privcmd_ops =
     }
 };
 
-static xc_osdep_handle ENOSYS_evtchn_open(xc_interface *xce)
-{
-    IPRINTF(xce, "ENOSYS_evtchn: opening handle %p\n", (void *)1);
-    return (xc_osdep_handle)2; /*dummy*/
-}
-
-static int ENOSYS_evtchn_close(xc_interface *xce, xc_osdep_handle h)
-{
-    IPRINTF(xce, "ENOSYS_evtchn: closing handle %lx\n", h);
-    return 0;
-}
-
-static int ENOSYS_evtchn_fd(xc_interface *xce, xc_osdep_handle h)
-{
-    IPRINTF(xce, "ENOSYS_fd %lx fd\n", h);
-    return (int)h;
-}
-
-static int ENOSYS_evtchn_notify(xc_interface *xce, xc_osdep_handle h, evtchn_port_t port)
-{
-    IPRINTF(xce, "ENOSYS_evtchn %lx notify: %d\n", h, port);
-    return -ENOSYS;
-}
-
-static int ENOSYS_evtchn_bind_unbound_port(xc_interface *xce, xc_osdep_handle h, int domid)
-{
-    IPRINTF(xce, "ENOSYS_evtchn %lx bind_unbound_port: dom%d\n", h, domid);
-    return -ENOSYS;
-}
-
-
-static int ENOSYS_evtchn_bind_interdomain(xc_interface *xce, xc_osdep_handle h, int domid, evtchn_port_t remote_port)
-{
-    IPRINTF(xce, "ENOSYS_evtchn %lx bind_interdomain: dmo%d %d\n", h, domid, remote_port);
-    return -ENOSYS;
-}
-
-
-static int ENOSYS_evtchn_bind_virq(xc_interface *xce, xc_osdep_handle h, unsigned int virq)
-{
-    IPRINTF(xce, "ENOSYS_evtchn %lx bind_virq: %d\n", h, virq);
-    return -ENOSYS;
-}
-
-
-static int ENOSYS_evtchn_unbind(xc_interface *xce, xc_osdep_handle h, evtchn_port_t port)
-{
-    IPRINTF(xce, "ENOSYS_evtchn %lx unbind: %d\n", h, port);
-    return -ENOSYS;
-}
-
-
-static evtchn_port_or_error_t ENOSYS_evtchn_pending(xc_interface *xce, xc_osdep_handle h)
-{
-    IPRINTF(xce, "ENOSYS_evtchn %lx pending\n", h);
-    return -ENOSYS;
-}
-
-static int ENOSYS_evtchn_unmask(xc_interface *xce, xc_osdep_handle h, evtchn_port_t port)
-{
-    IPRINTF(xce, "ENOSYS_evtchn %lx unmask: %d\n", h, port);
-    return -ENOSYS;
-}
-
-static struct xc_osdep_ops ENOSYS_evtchn_ops = {
-    .open = &ENOSYS_evtchn_open,
-    .close = &ENOSYS_evtchn_close,
-
-    .u.evtchn = {
-        .fd = &ENOSYS_evtchn_fd,
-
-        .notify = &ENOSYS_evtchn_notify,
-
-        .bind_unbound_port = &ENOSYS_evtchn_bind_unbound_port,
-        .bind_interdomain = &ENOSYS_evtchn_bind_interdomain,
-        .bind_virq = &ENOSYS_evtchn_bind_virq,
-
-        .unbind = &ENOSYS_evtchn_unbind,
-
-        .pending = &ENOSYS_evtchn_pending,
-        .unmask = &ENOSYS_evtchn_unmask,
-    },
-};
-
 static struct xc_osdep_ops * ENOSYS_osdep_init(xc_interface *xch, enum xc_osdep_type type)
 {
     struct xc_osdep_ops *ops;
@@ -180,9 +96,6 @@ static struct xc_osdep_ops * ENOSYS_osdep_init(xc_interface *xch, enum xc_osdep_
     case XC_OSDEP_PRIVCMD:
         ops = &ENOSYS_privcmd_ops;
         break;
-    case XC_OSDEP_EVTCHN:
-        ops = &ENOSYS_evtchn_ops;
-        break;
     default:
         ops = NULL;
         break;
diff --git a/tools/ocaml/libs/eventchn/xeneventchn_stubs.c b/tools/ocaml/libs/eventchn/xeneventchn_stubs.c
index abefd6b..5939e7c 100644
--- a/tools/ocaml/libs/eventchn/xeneventchn_stubs.c
+++ b/tools/ocaml/libs/eventchn/xeneventchn_stubs.c
@@ -34,14 +34,14 @@
 #include <caml/callback.h>
 #include <caml/fail.h>
 
-#define _H(__h) ((xc_interface *)(__h))
+#define _H(__h) ((xc_evtchn *)(__h))
 
 CAMLprim value stub_eventchn_init(void)
 {
 	CAMLparam0();
 	CAMLlocal1(result);
 
-	xc_interface *xce = xc_evtchn_open(NULL, XC_OPENFLAG_NON_REENTRANT);
+	xc_evtchn *xce = xc_evtchn_open(NULL, XC_OPENFLAG_NON_REENTRANT);
 	if (xce == NULL)
 		caml_failwith("open failed");
 
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH XEN v2 05/15] tools: Refactor /dev/xen/evtchn wrappers into libxenevtchn.
  2015-07-15 15:46 [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries Ian Campbell
                   ` (3 preceding siblings ...)
  2015-07-15 15:46 ` [PATCH XEN v2 04/15] tools/libxc: Remove osdep indirection for xc_evtchn Ian Campbell
@ 2015-07-15 15:46 ` Ian Campbell
  2015-09-21 15:53   ` Ian Campbell
  2015-07-15 15:46 ` [PATCH XEN v2 06/15] tools: Arrange to check public headers for ANSI compatiblity Ian Campbell
                   ` (22 subsequent siblings)
  27 siblings, 1 reply; 55+ messages in thread
From: Ian Campbell @ 2015-07-15 15:46 UTC (permalink / raw)
  To: ian.jackson, wei.liu2, xen-devel
  Cc: roger.pau, Ian Campbell, stefano.stabellini

libxenevtchn will provide a stable API and ABI for accessing the
evtchn device.

The functions are moved into the xenevtchn namespace to make a clean
break from libxc and avoid ambiguity regarding which interfaces are
stable.

All in-tree users are updated to use the new names.

Upon request (via #define XC_WANT_COMPAT_EVTCHN_API) libxenctrl will
provide a compat API for the old names. This is used by qemu-xen for
the time being. qemu-xen-traditional is updated in lockstep.

This leaves a few event channel related functions which go via privcmd
(EVTCHNOP) rather than ioctls on the /dev/xen/evtchn device in
libxenctrl. Specifically:

 - xc_evtchn_alloc_unbound
 - xc_evtchn_reset
 - xc_evtchn_status

Note that xc_evtchn_alloc_unbound's functionality is also provided by
xenevtchn_bind_unbound_port() (née xc_evtchn_bind_unbound_port) and is
probably redundant.

These functions do not appear to be needed by qemu-dm, qemu-pv
(provision of device model to HVM guests and PV backends respectively)
or by libvchan suggesting they are not needed by non-toolstack uses of
event channels. QEMU does use these in hw/xenpv/xen_domainbuild.c but
that is a "toolstack use".

The new library uses a version script to ensure that only expected
symbols are exported and to version them such that ABI guarantees can
be kept in the future.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
---

Must be applied with:

 - "qemu-xen-traditional: Use libxenevtchn" and a corresponding
   QEMU_TAG update folded here.
 - "mini-os: Include libxenevtchn with libxc"" and a corresponding
   bump to MINIOS_UPSTREAM_REVISION folded in here.

v2: Update doc at same time
    Removed some stray compat thing
---
 .gitignore                                    |   1 +
 docs/misc/toolstack-library-abis.pandoc       |  38 ++--
 stubdom/Makefile                              |  19 +-
 tools/Makefile                                |   6 +-
 tools/Rules.mk                                |  14 +-
 tools/console/Makefile                        |   2 +
 tools/console/daemon/io.c                     |  43 +++--
 tools/libvchan/Makefile                       |   6 +-
 tools/libvchan/init.c                         |  20 +-
 tools/libvchan/io.c                           |  12 +-
 tools/libvchan/libxenvchan.h                  |   3 +-
 tools/libxc/Makefile                          |   8 +-
 tools/libxc/include/xenctrl.h                 |  99 +---------
 tools/libxc/include/xenctrl_compat.h          |  48 +++++
 tools/libxc/include/xenguest.h                |  10 +-
 tools/libxc/xc_evtchn_compat.c                |  75 ++++++++
 tools/libxc/xc_freebsd_osdep.c                | 101 ----------
 tools/libxc/xc_linux_osdep.c                  |  95 ---------
 tools/libxc/xc_minios.c                       | 221 ---------------------
 tools/libxc/xc_netbsd.c                       | 109 -----------
 tools/libxc/xc_private.c                      |  40 ----
 tools/libxc/xc_private.h                      |   7 -
 tools/libxc/xc_solaris.c                      |  97 ----------
 tools/libxc/xc_suspend.c                      |  18 +-
 tools/libxenevtchn/Makefile                   |  65 +++++++
 tools/libxenevtchn/core.c                     |  70 +++++++
 tools/libxenevtchn/freebsd.c                  | 135 +++++++++++++
 tools/libxenevtchn/include/xenevtchn.h        | 147 ++++++++++++++
 tools/libxenevtchn/libxenevtchn.map           |  14 ++
 tools/libxenevtchn/linux.c                    | 133 +++++++++++++
 tools/libxenevtchn/minios.c                   | 266 ++++++++++++++++++++++++++
 tools/libxenevtchn/netbsd.c                   | 144 ++++++++++++++
 tools/libxenevtchn/private.h                  |  25 +++
 tools/libxenevtchn/solaris.c                  | 132 +++++++++++++
 tools/libxentoollog/include/xentoollog.h      |  10 +
 tools/libxentoollog/xtl_core.c                |  10 +
 tools/libxentoollog/xtl_logger_stdio.c        |  10 +
 tools/libxl/Makefile                          |   5 +-
 tools/libxl/libxl.c                           |   2 +-
 tools/libxl/libxl_dom.c                       |   4 +-
 tools/libxl/libxl_event.c                     |  14 +-
 tools/libxl/libxl_internal.h                  |   5 +-
 tools/misc/Makefile                           |   7 +-
 tools/misc/xen-hptool.c                       |  13 +-
 tools/misc/xen-lowmemd.c                      |  15 +-
 tools/ocaml/libs/eventchn/Makefile            |   4 +-
 tools/ocaml/libs/eventchn/xeneventchn_stubs.c |  20 +-
 tools/python/setup.py                         |   7 +-
 tools/tests/xen-access/xen-access.c           |   2 +-
 tools/xcutils/Makefile                        |   4 +-
 tools/xenmon/Makefile                         |   2 +
 tools/xenmon/xenbaked.c                       |  13 +-
 tools/xenpaging/Makefile                      |   4 +-
 tools/xenpaging/xenpaging.c                   |  18 +-
 tools/xenpaging/xenpaging.h                   |   3 +-
 tools/xenstore/Makefile                       |   5 +-
 tools/xenstore/xenstored_core.c               |   6 +-
 tools/xenstore/xenstored_domain.c             |  25 +--
 tools/xentrace/Makefile                       |   5 +-
 tools/xentrace/xentrace.c                     |  13 +-
 60 files changed, 1520 insertions(+), 929 deletions(-)
 create mode 100644 tools/libxc/include/xenctrl_compat.h
 create mode 100644 tools/libxc/xc_evtchn_compat.c
 create mode 100644 tools/libxenevtchn/Makefile
 create mode 100644 tools/libxenevtchn/core.c
 create mode 100644 tools/libxenevtchn/freebsd.c
 create mode 100644 tools/libxenevtchn/include/xenevtchn.h
 create mode 100644 tools/libxenevtchn/libxenevtchn.map
 create mode 100644 tools/libxenevtchn/linux.c
 create mode 100644 tools/libxenevtchn/minios.c
 create mode 100644 tools/libxenevtchn/netbsd.c
 create mode 100644 tools/libxenevtchn/private.h
 create mode 100644 tools/libxenevtchn/solaris.c

diff --git a/.gitignore b/.gitignore
index e56487a..ed6bac6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -60,6 +60,7 @@ stubdom/include
 stubdom/ioemu
 stubdom/xenstore
 stubdom/libxentoollog-*
+stubdom/libxenevtchn-*
 stubdom/libxc-*
 stubdom/lwip-*
 stubdom/mini-os-*
diff --git a/docs/misc/toolstack-library-abis.pandoc b/docs/misc/toolstack-library-abis.pandoc
index 68e6742..d7ae875 100644
--- a/docs/misc/toolstack-library-abis.pandoc
+++ b/docs/misc/toolstack-library-abis.pandoc
@@ -111,6 +111,23 @@ Interface                     Known external users
 `xtl_stdiostream_adjust_flags`
 `xtl_stdiostream_set_minlevel`
 
+## `libxenevtchn`: event channels
+
+Interacting with Event Channels via `/dev/xen/evtchn`.
+
+Interface                     Underlying interface             Known external users
+----------------------------- -------------------------------- --------------------
+`xenevtchn_bind_interdomain`  `IOCTL_EVTCHN_BIND_INTERDOMAIN`  qemu-pv
+`xenevtchn_bind_unbound_port` `IOCTL_EVTCHN_BIND_UNBOUND_PORT`
+`xenevtchn_bind_virq`         `IOCTL_EVTCHN_BIND_VIRQ`
+`xenevtchn_close`             `close(2)`                       qemu-dm
+`xenevtchn_fd`
+`xenevtchn_notify`            `IOCTL_EVTCHN_NOTIFY`            qemu-dm, qemu-pv
+`xenevtchn_open`              `open(2)`                        qemu-dm, qemu-pv
+`xenevtchn_pending`           `read(2)`                        qemu-dm, qemu-pv
+`xenevtchn_unbind`            `IOCTL_EVTCHN_UNBIND`            qemu-pv
+`xenevtchn_unmask`            `write(2)`                       qemu-dm, qemu-pv
+
 # Unstable libraries
 
 These libraries do not provide a stable interface and are required to
@@ -153,20 +170,10 @@ Notes:
 ### Event channels
 
 Interacting with Event Channels via `__HYPERVISOR_event_channel_op`
-(`EVTCHNOP_*`) or `/dev/xen/evtchn`.
+(`EVTCHNOP_*`).
 
 Interface                     Underlying interface             Known external users
 ----------------------------- -------------------------------- --------------------
-`xc_evtchn_bind_interdomain`  `IOCTL_EVTCHN_BIND_INTERDOMAIN`  qemu-pv
-`xc_evtchn_bind_unbound_port` `IOCTL_EVTCHN_BIND_UNBOUND_PORT`
-`xc_evtchn_bind_virq`         `IOCTL_EVTCHN_BIND_VIRQ`
-`xc_evtchn_close`             `close(2)`                       qemu-dm
-`xc_evtchn_fd`
-`xc_evtchn_notify`            `IOCTL_EVTCHN_NOTIFY`            qemu-dm, qemu-pv
-`xc_evtchn_open`              `open(2)`                        qemu-dm, qemu-pv
-`xc_evtchn_pending`           `read(2)`                        qemu-dm, qemu-pv
-`xc_evtchn_unbind`            `IOCTL_EVTCHN_UNBIND`            qemu-pv
-`xc_evtchn_unmask`            `write(2)`                       qemu-dm, qemu-pv
 `xc_evtchn_alloc_unbound`     `EVTCHNOP_alloc_unbound`
 `xc_evtchn_reset`             `EVTCHNOP_reset`
 `xc_evtchn_status`            `EVTCHNOP_status`
@@ -726,11 +733,14 @@ Gathered by:
     - xc_mark_page_online
     - xc_query_page_offline_status
     - xc_read_image
-    - xc_suspend_evtchn_init_exclusive
-    - xc_suspend_evtchn_init_sane
-    - xc_suspend_evtchn_release
     - xc_try_lz4_decode
 
+Use privcmd and evtchn device handles:
+
+    - xc_suspend_evtchn_init_exclusive. Used by xen-hptool and libxl.
+    - xc_suspend_evtchn_init_sane. Unused
+    - xc_suspend_evtchn_release. Used by xen-hptool and libxl.
+
 # Consumers of `libxenctrl` functionality
 
 ## `qemu`
diff --git a/stubdom/Makefile b/stubdom/Makefile
index b8b0d43..b4dd39a 100644
--- a/stubdom/Makefile
+++ b/stubdom/Makefile
@@ -318,6 +318,12 @@ mk-headers-$(XEN_TARGET_ARCH): $(IOEMU_LINKFARM_TARGET)
 	  ln -sf $(XEN_ROOT)/tools/libxentoollog/include/*.h . && \
 	  ln -sf $(XEN_ROOT)/tools/libxentoollog/*.c . && \
 	  ln -sf $(XEN_ROOT)/tools/libxentoollog/Makefile . )
+	mkdir -p libxenevtchn-$(XEN_TARGET_ARCH)/include
+	[ -h libxenevtchn-$(XEN_TARGET_ARCH)/Makefile ] || ( cd libxenevtchn-$(XEN_TARGET_ARCH) && \
+	  ln -sf $(XEN_ROOT)/tools/libxenevtchn/*.h . && \
+	  ln -sf $(XEN_ROOT)/tools/libxenevtchn/include/*.h include/ && \
+	  ln -sf $(XEN_ROOT)/tools/libxenevtchn/*.c . && \
+	  ln -sf $(XEN_ROOT)/tools/libxenevtchn/Makefile . )
 	mkdir -p libxc-$(XEN_TARGET_ARCH)
 	[ -h libxc-$(XEN_TARGET_ARCH)/Makefile ] || ( cd libxc-$(XEN_TARGET_ARCH) && \
 	  ln -sf $(XEN_ROOT)/tools/libxc/*.h . && \
@@ -352,12 +358,23 @@ libxentoollog-$(XEN_TARGET_ARCH)/libxentoollog.a: $(NEWLIB_STAMPFILE)
 	CPPFLAGS="$(TARGET_CPPFLAGS)" CFLAGS="$(TARGET_CFLAGS)" $(MAKE) DESTDIR= -C libxentoollog-$(XEN_TARGET_ARCH)
 
 #######
+# libxenevtchn
+#######
+
+.PHONY: libxenevtchn
+libxenevtchn: libxenevtchn-$(XEN_TARGET_ARCH)/libxenevtchn.a
+libxenevtchn-$(XEN_TARGET_ARCH)/libxenevtchn.a: $(NEWLIB_STAMPFILE)
+	$(MAKE) -C $(XEN_ROOT)/tools/include
+	$(MAKE) DESTDIR= -C $(MINI_OS) links
+	CPPFLAGS="$(TARGET_CPPFLAGS)" CFLAGS="$(TARGET_CFLAGS)" $(MAKE) DESTDIR= -C libxenevtchn-$(XEN_TARGET_ARCH)
+
+#######
 # libxc
 #######
 
 .PHONY: libxc
 libxc: libxc-$(XEN_TARGET_ARCH)/libxenctrl.a libxc-$(XEN_TARGET_ARCH)/libxenguest.a
-libxc-$(XEN_TARGET_ARCH)/libxenctrl.a: libxentoollog cross-zlib
+libxc-$(XEN_TARGET_ARCH)/libxenctrl.a: libxentoollog libxenevtchn cross-zlib
 	$(MAKE) -C $(XEN_ROOT)/tools/include
 	$(MAKE) DESTDIR= -C $(MINI_OS) links
 	CPPFLAGS="$(TARGET_CPPFLAGS)" CFLAGS="$(TARGET_CFLAGS)" $(MAKE) DESTDIR= CONFIG_LIBXC_MINIOS=y -C libxc-$(XEN_TARGET_ARCH)
diff --git a/tools/Makefile b/tools/Makefile
index 777591a..3497c53 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -4,6 +4,7 @@ include $(XEN_ROOT)/tools/Rules.mk
 SUBDIRS-y :=
 SUBDIRS-y += include
 SUBDIRS-y += libxentoollog
+SUBDIRS-y += libxenevtchn
 SUBDIRS-y += libxc
 SUBDIRS-$(FLASK_ENABLE) += flask
 SUBDIRS-y += xenstore
@@ -248,8 +249,10 @@ subdir-all-qemu-xen-dir: qemu-xen-dir-find
 		--libdir=$(LIBEXEC_LIB) \
 		--includedir=$(LIBEXEC_INC) \
 		--source-path=$$source \
-		--extra-cflags="-I$(XEN_ROOT)/tools/include \
+		--extra-cflags="-DXC_WANT_COMPAT_EVTCHN_API=1 \
+		-I$(XEN_ROOT)/tools/include \
 		-I$(XEN_ROOT)/tools/libxentoollog/include \
+		-I$(XEN_ROOT)/tools/libxenevtchn/include \
 		-I$(XEN_ROOT)/tools/libxc/include \
 		-I$(XEN_ROOT)/tools/xenstore/include \
 		-I$(XEN_ROOT)/tools/xenstore/compat/include \
@@ -257,6 +260,7 @@ subdir-all-qemu-xen-dir: qemu-xen-dir-find
 		--extra-ldflags="-L$(XEN_ROOT)/tools/libxc \
 		-L$(XEN_ROOT)/tools/xenstore \
 		-Wl,-rpath-link=$(XEN_ROOT)/tools/libxentoollog \
+		-Wl,-rpath-link=$(XEN_ROOT)/tools/libxenevtchn \
 		$(QEMU_UPSTREAM_RPATH)" \
 		--bindir=$(LIBEXEC_BIN) \
 		--datadir=$(SHAREDIR)/qemu-xen \
diff --git a/tools/Rules.mk b/tools/Rules.mk
index 11227c7..e200eb7 100644
--- a/tools/Rules.mk
+++ b/tools/Rules.mk
@@ -11,6 +11,7 @@ INSTALL = $(XEN_ROOT)/tools/cross-install
 
 XEN_INCLUDE        = $(XEN_ROOT)/tools/include
 XEN_LIBXENTOOLLOG  = $(XEN_ROOT)/tools/libxentoollog
+XEN_LIBXENEVTCHN   = $(XEN_ROOT)/tools/libxenevtchn
 XEN_LIBXC          = $(XEN_ROOT)/tools/libxc
 XEN_XENLIGHT       = $(XEN_ROOT)/tools/libxl
 XEN_XENSTORE       = $(XEN_ROOT)/tools/xenstore
@@ -82,13 +83,18 @@ SHDEPS_libxentoollog =
 LDLIBS_libxentoollog = $(XEN_LIBXENTOOLLOG)/libxentoollog$(libextension)
 SHLIB_libxentoollog  = -Wl,-rpath-link=$(XEN_LIBXENTOOLLOG)
 
+CFLAGS_libxenevtchn = -I$(XEN_LIBXENEVTCHN)/include $(CFLAGS_xeninclude)
+SHDEPS_libxenevtchn =
+LDLIBS_libxenevtchn = $(XEN_LIBXENEVTCHN)/libxenevtchn$(libextension)
+SHLIB_libxenevtchn  = -Wl,-rpath-link=$(XEN_LIBXENEVTCHN)
+
 CFLAGS_libxenctrl = -I$(XEN_LIBXC)/include $(CFLAGS_libxentoollog) $(CFLAGS_xeninclude)
-SHDEPS_libxenctrl = $(SHLIB_libxentoollog) 
+SHDEPS_libxenctrl = $(SHLIB_libxentoollog) $(SHLIB_libxenevtchn)
 LDLIBS_libxenctrl = $(SHDEPS_libxenctrl) $(XEN_LIBXC)/libxenctrl$(libextension)
 SHLIB_libxenctrl  = $(SHDEPS_libxenctrl) -Wl,-rpath-link=$(XEN_LIBXC)
 
-CFLAGS_libxenguest = -I$(XEN_LIBXC)/include $(CFLAGS_xeninclude)
-SHDEPS_libxenguest =
+CFLAGS_libxenguest = -I$(XEN_LIBXC)/include $(CFLAGS_libxenevtchn) $(CFLAGS_xeninclude)
+SHDEPS_libxenguest = $(SHLIB_libxenevtchn)
 LDLIBS_libxenguest = $(SHDEPS_libxenguest) $(XEN_LIBXC)/libxenguest$(libextension)
 SHLIB_libxenguest  = $(SHDEPS_libxenguest) -Wl,-rpath-link=L$(XEN_LIBXC)
 
@@ -103,7 +109,7 @@ LDLIBS_libxenstat  = $(SHDEPS_libxenstat) $(XEN_LIBXENSTAT)/libxenstat$(libexten
 SHLIB_libxenstat   = $(SHDEPS_libxenstat) -Wl,-rpath-link=$(XEN_LIBXENSTAT)
 
 CFLAGS_libxenvchan = -I$(XEN_LIBVCHAN)
-SHDEPS_libxenvchan = $(SHLIB_libxenctrl) $(SHLIB_libxenstore)
+SHDEPS_libxenvchan = $(SHLIB_libxenctrl) $(SHLIB_libxenstore) $(SHLIB_libxenevtchn)
 LDLIBS_libxenvchan = $(SHDEPS_libxenvchan) $(XEN_LIBVCHAN)/libxenvchan$(libextension)
 SHLIB_libxenvchan  = $(SHDEPS_libxenvchan) -Wl,-rpath-link=$(XEN_LIBVCHAN)
 
diff --git a/tools/console/Makefile b/tools/console/Makefile
index 71f8088..0141d7f 100644
--- a/tools/console/Makefile
+++ b/tools/console/Makefile
@@ -3,8 +3,10 @@ include $(XEN_ROOT)/tools/Rules.mk
 
 CFLAGS  += -Werror
 
+CFLAGS  += $(CFLAGS_libxenevtchn)
 CFLAGS  += $(CFLAGS_libxenctrl)
 CFLAGS  += $(CFLAGS_libxenstore)
+LDLIBS += $(LDLIBS_libxenevtchn)
 LDLIBS += $(LDLIBS_libxenctrl)
 LDLIBS += $(LDLIBS_libxenstore)
 LDLIBS += $(SOCKET_LIBS)
diff --git a/tools/console/daemon/io.c b/tools/console/daemon/io.c
index e246c25..8829b09 100644
--- a/tools/console/daemon/io.c
+++ b/tools/console/daemon/io.c
@@ -22,6 +22,7 @@
 
 #include "utils.h"
 #include "io.h"
+#include <xenevtchn.h>
 #include <xenstore.h>
 #include <xen/io/console.h>
 #include <xen/grant_table.h>
@@ -102,7 +103,7 @@ struct domain {
 	int ring_ref;
 	evtchn_port_or_error_t local_port;
 	evtchn_port_or_error_t remote_port;
-	xc_evtchn *xce_handle;
+	xenevtchn_handle *xce_handle;
 	int xce_pollfd_idx;
 	struct xencons_interface *interface;
 	int event_count;
@@ -186,7 +187,7 @@ static void buffer_append(struct domain *dom)
 
 	xen_mb();
 	intf->out_cons = cons;
-	xc_evtchn_notify(dom->xce_handle, dom->local_port);
+	xenevtchn_notify(dom->xce_handle, dom->local_port);
 
 	/* Get the data to the logfile as early as possible because if
 	 * no one is listening on the console pty then it will fill up
@@ -585,22 +586,22 @@ static int domain_create_ring(struct domain *dom)
 	dom->local_port = -1;
 	dom->remote_port = -1;
 	if (dom->xce_handle != NULL)
-		xc_evtchn_close(dom->xce_handle);
+		xenevtchn_close(dom->xce_handle);
 
 	/* Opening evtchn independently for each console is a bit
 	 * wasteful, but that's how the code is structured... */
-	dom->xce_handle = xc_evtchn_open(NULL, 0);
+	dom->xce_handle = xenevtchn_open(NULL, 0);
 	if (dom->xce_handle == NULL) {
 		err = errno;
 		goto out;
 	}
  
-	rc = xc_evtchn_bind_interdomain(dom->xce_handle,
+	rc = xenevtchn_bind_interdomain(dom->xce_handle,
 		dom->domid, remote_port);
 
 	if (rc == -1) {
 		err = errno;
-		xc_evtchn_close(dom->xce_handle);
+		xenevtchn_close(dom->xce_handle);
 		dom->xce_handle = NULL;
 		goto out;
 	}
@@ -610,7 +611,7 @@ static int domain_create_ring(struct domain *dom)
 	if (dom->master_fd == -1) {
 		if (!domain_create_tty(dom)) {
 			err = errno;
-			xc_evtchn_close(dom->xce_handle);
+			xenevtchn_close(dom->xce_handle);
 			dom->xce_handle = NULL;
 			dom->local_port = -1;
 			dom->remote_port = -1;
@@ -750,7 +751,7 @@ static void shutdown_domain(struct domain *d)
 	watch_domain(d, false);
 	domain_unmap_interface(d);
 	if (d->xce_handle != NULL)
-		xc_evtchn_close(d->xce_handle);
+		xenevtchn_close(d->xce_handle);
 	d->xce_handle = NULL;
 }
 
@@ -840,7 +841,7 @@ static void handle_tty_read(struct domain *dom)
 		}
 		xen_wmb();
 		intf->in_prod = prod;
-		xc_evtchn_notify(dom->xce_handle, dom->local_port);
+		xenevtchn_notify(dom->xce_handle, dom->local_port);
 	} else {
 		domain_close_tty(dom);
 		shutdown_domain(dom);
@@ -872,7 +873,7 @@ static void handle_ring_read(struct domain *dom)
 	if (dom->is_dead)
 		return;
 
-	if ((port = xc_evtchn_pending(dom->xce_handle)) == -1)
+	if ((port = xenevtchn_pending(dom->xce_handle)) == -1)
 		return;
 
 	dom->event_count++;
@@ -880,7 +881,7 @@ static void handle_ring_read(struct domain *dom)
 	buffer_append(dom);
 
 	if (dom->event_count < RATE_LIMIT_ALLOWANCE)
-		(void)xc_evtchn_unmask(dom->xce_handle, port);
+		(void)xenevtchn_unmask(dom->xce_handle, port);
 }
 
 static void handle_xs(void)
@@ -907,7 +908,7 @@ static void handle_xs(void)
 	free(vec);
 }
 
-static void handle_hv_logs(xc_evtchn *xce_handle, bool force)
+static void handle_hv_logs(xenevtchn_handle *xce_handle, bool force)
 {
 	static char buffer[1024*16];
 	char *bufptr = buffer;
@@ -915,7 +916,7 @@ static void handle_hv_logs(xc_evtchn *xce_handle, bool force)
 	static uint32_t index = 0;
 	evtchn_port_or_error_t port = -1;
 
-	if (!force && ((port = xc_evtchn_pending(xce_handle)) == -1))
+	if (!force && ((port = xenevtchn_pending(xce_handle)) == -1))
 		return;
 
 	do
@@ -939,7 +940,7 @@ static void handle_hv_logs(xc_evtchn *xce_handle, bool force)
 	} while (size == sizeof(buffer));
 
 	if (port != -1)
-		(void)xc_evtchn_unmask(xce_handle, port);
+		(void)xenevtchn_unmask(xce_handle, port);
 }
 
 static void handle_log_reload(void)
@@ -1007,10 +1008,10 @@ void handle_io(void)
 	evtchn_port_or_error_t log_hv_evtchn = -1;
 	int xce_pollfd_idx = -1;
 	int xs_pollfd_idx = -1;
-	xc_evtchn *xce_handle = NULL;
+	xenevtchn_handle *xce_handle = NULL;
 
 	if (log_hv) {
-		xce_handle = xc_evtchn_open(NULL, 0);
+		xce_handle = xenevtchn_open(NULL, 0);
 		if (xce_handle == NULL) {
 			dolog(LOG_ERR, "Failed to open xce handle: %d (%s)",
 			      errno, strerror(errno));
@@ -1019,7 +1020,7 @@ void handle_io(void)
 		log_hv_fd = create_hv_log();
 		if (log_hv_fd == -1)
 			goto out;
-		log_hv_evtchn = xc_evtchn_bind_virq(xce_handle, VIRQ_CON_RING);
+		log_hv_evtchn = xenevtchn_bind_virq(xce_handle, VIRQ_CON_RING);
 		if (log_hv_evtchn == -1) {
 			dolog(LOG_ERR, "Failed to bind to VIRQ_CON_RING: "
 			      "%d (%s)", errno, strerror(errno));
@@ -1048,7 +1049,7 @@ void handle_io(void)
 		xs_pollfd_idx = set_fds(xs_fileno(xs), POLLIN|POLLPRI);
 
 		if (log_hv)
-			xce_pollfd_idx = set_fds(xc_evtchn_fd(xce_handle),
+			xce_pollfd_idx = set_fds(xenevtchn_fd(xce_handle),
 						 POLLIN|POLLPRI);
 
 		if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0)
@@ -1067,7 +1068,7 @@ void handle_io(void)
 			if ((now+5) > d->next_period) {
 				d->next_period = now + RATE_LIMIT_PERIOD;
 				if (d->event_count >= RATE_LIMIT_ALLOWANCE) {
-					(void)xc_evtchn_unmask(d->xce_handle, d->local_port);
+					(void)xenevtchn_unmask(d->xce_handle, d->local_port);
 				}
 				d->event_count = 0;
 			}
@@ -1083,7 +1084,7 @@ void handle_io(void)
 				if (discard_overflowed_data ||
 				    !d->buffer.max_capacity ||
 				    d->buffer.size < d->buffer.max_capacity) {
-					int evtchn_fd = xc_evtchn_fd(d->xce_handle);
+					int evtchn_fd = xenevtchn_fd(d->xce_handle);
 					d->xce_pollfd_idx = set_fds(evtchn_fd,
 								    POLLIN|POLLPRI);
 				}
@@ -1203,7 +1204,7 @@ void handle_io(void)
 		log_hv_fd = -1;
 	}
 	if (xce_handle != NULL) {
-		xc_evtchn_close(xce_handle);
+		xenevtchn_close(xce_handle);
 		xce_handle = NULL;
 	}
 	if (xcg_handle != NULL) {
diff --git a/tools/libvchan/Makefile b/tools/libvchan/Makefile
index 3c50fe6..84128a3 100644
--- a/tools/libvchan/Makefile
+++ b/tools/libvchan/Makefile
@@ -10,9 +10,9 @@ NODE_OBJS = node.o
 NODE2_OBJS = node-select.o
 
 LIBVCHAN_PIC_OBJS = $(patsubst %.o,%.opic,$(LIBVCHAN_OBJS))
-LIBVCHAN_LIBS = $(LDLIBS_libxenstore) $(LDLIBS_libxenctrl)
-$(LIBVCHAN_OBJS) $(LIBVCHAN_PIC_OBJS): CFLAGS += $(CFLAGS_libxenstore) $(CFLAGS_libxenctrl)
-$(NODE_OBJS) $(NODE2_OBJS): CFLAGS += $(CFLAGS_libxenctrl)
+LIBVCHAN_LIBS = $(LDLIBS_libxenstore) $(LDLIBS_libxenctrl) $(LDLIBS_libxenevtchn)
+$(LIBVCHAN_OBJS) $(LIBVCHAN_PIC_OBJS): CFLAGS += $(CFLAGS_libxenstore) $(CFLAGS_libxenctrl) $(CFLAGS_libxenevtchn)
+$(NODE_OBJS) $(NODE2_OBJS): CFLAGS += $(CFLAGS_libxenctrl) $(CFLAGS_libxenevtchn)
 
 MAJOR = 1.0
 MINOR = 0
diff --git a/tools/libvchan/init.c b/tools/libvchan/init.c
index de10817..fef6c8d 100644
--- a/tools/libvchan/init.c
+++ b/tools/libvchan/init.c
@@ -217,25 +217,25 @@ static int init_evt_srv(struct libxenvchan *ctrl, int domain, xentoollog_logger
 {
 	evtchn_port_or_error_t port;
 
-	ctrl->event = xc_evtchn_open(logger, 0);
+	ctrl->event = xenevtchn_open(logger, 0);
 	if (!ctrl->event)
 		return -1;
 
-	port = xc_evtchn_bind_unbound_port(ctrl->event, domain);
+	port = xenevtchn_bind_unbound_port(ctrl->event, domain);
 	if (port < 0)
 		goto fail;
 	ctrl->event_port = port;
 
-	if (xc_evtchn_unmask(ctrl->event, ctrl->event_port))
+	if (xenevtchn_unmask(ctrl->event, ctrl->event_port))
 		goto fail;
 
 	return 0;
 
 fail:
 	if (port >= 0)
-		xc_evtchn_unbind(ctrl->event, port);
+		xenevtchn_unbind(ctrl->event, port);
 
-	xc_evtchn_close(ctrl->event);
+	xenevtchn_close(ctrl->event);
 	ctrl->event = NULL;
 
 	return -1;
@@ -347,26 +347,26 @@ static int init_evt_cli(struct libxenvchan *ctrl, int domain, xentoollog_logger
 {
 	evtchn_port_or_error_t port;
 
-	ctrl->event = xc_evtchn_open(logger, 0);
+	ctrl->event = xenevtchn_open(logger, 0);
 	if (!ctrl->event)
 		return -1;
 
-	port = xc_evtchn_bind_interdomain(ctrl->event,
+	port = xenevtchn_bind_interdomain(ctrl->event,
 		domain, ctrl->event_port);
 	if (port < 0)
 		goto fail;
 	ctrl->event_port = port;
 
-	if (xc_evtchn_unmask(ctrl->event, ctrl->event_port))
+	if (xenevtchn_unmask(ctrl->event, ctrl->event_port))
 		goto fail;
 
 	return 0;
 
 fail:
 	if (port >= 0)
-		xc_evtchn_unbind(ctrl->event, port);
+		xenevtchn_unbind(ctrl->event, port);
 
-	xc_evtchn_close(ctrl->event);
+	xenevtchn_close(ctrl->event);
 	ctrl->event = NULL;
 
 	return -1;
diff --git a/tools/libvchan/io.c b/tools/libvchan/io.c
index e66bc4e..4bd15ed 100644
--- a/tools/libvchan/io.c
+++ b/tools/libvchan/io.c
@@ -106,7 +106,7 @@ static inline int send_notify(struct libxenvchan *ctrl, uint8_t bit)
 	notify = ctrl->is_server ? &ctrl->ring->srv_notify : &ctrl->ring->cli_notify;
 	prev = __sync_fetch_and_and(notify, ~bit);
 	if (prev & bit)
-		return xc_evtchn_notify(ctrl->event, ctrl->event_port);
+		return xenevtchn_notify(ctrl->event, ctrl->event_port);
 	else
 		return 0;
 }
@@ -195,10 +195,10 @@ int libxenvchan_buffer_space(struct libxenvchan *ctrl)
 
 int libxenvchan_wait(struct libxenvchan *ctrl)
 {
-	int ret = xc_evtchn_pending(ctrl->event);
+	int ret = xenevtchn_pending(ctrl->event);
 	if (ret < 0)
 		return -1;
-	xc_evtchn_unmask(ctrl->event, ret);
+	xenevtchn_unmask(ctrl->event, ret);
 	return 0;
 }
 
@@ -351,7 +351,7 @@ int libxenvchan_is_open(struct libxenvchan* ctrl)
 
 int libxenvchan_fd_for_select(struct libxenvchan *ctrl)
 {
-	return xc_evtchn_fd(ctrl->event);
+	return xenevtchn_fd(ctrl->event);
 }
 
 void libxenvchan_close(struct libxenvchan *ctrl)
@@ -373,8 +373,8 @@ void libxenvchan_close(struct libxenvchan *ctrl)
 	}
 	if (ctrl->event) {
 		if (ctrl->ring)
-			xc_evtchn_notify(ctrl->event, ctrl->event_port);
-		xc_evtchn_close(ctrl->event);
+			xenevtchn_notify(ctrl->event, ctrl->event_port);
+		xenevtchn_close(ctrl->event);
 	}
 	if (ctrl->is_server) {
 		if (ctrl->gntshr)
diff --git a/tools/libvchan/libxenvchan.h b/tools/libvchan/libxenvchan.h
index 6365d36..0517dda 100644
--- a/tools/libvchan/libxenvchan.h
+++ b/tools/libvchan/libxenvchan.h
@@ -45,6 +45,7 @@
 
 #include <xen/io/libxenvchan.h>
 #include <xen/sys/evtchn.h>
+#include <xenevtchn.h>
 #include <xenctrl.h>
 
 struct libxenvchan_ring {
@@ -72,7 +73,7 @@ struct libxenvchan {
 	/* Pointer to shared ring page */
 	struct vchan_interface *ring;
 	/* event channel interface */
-	xc_evtchn *event;
+	xenevtchn_handle *event;
 	uint32_t event_port;
 	/* informative flags: are we acting as server? */
 	int is_server:1;
diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile
index feb6125..baf054f 100644
--- a/tools/libxc/Makefile
+++ b/tools/libxc/Makefile
@@ -47,6 +47,7 @@ CTRL_SRCS-$(CONFIG_SunOS) += xc_solaris.c
 CTRL_SRCS-$(CONFIG_NetBSD) += xc_netbsd.c
 CTRL_SRCS-$(CONFIG_NetBSDRump) += xc_netbsd.c
 CTRL_SRCS-$(CONFIG_MiniOS) += xc_minios.c
+CTRL_SRCS-y       += xc_evtchn_compat.c
 
 GUEST_SRCS-y :=
 GUEST_SRCS-y += xg_private.c xc_suspend.c
@@ -112,6 +113,7 @@ CFLAGS-$(CONFIG_Linux) += -D_GNU_SOURCE
 
 CFLAGS	+= $(PTHREAD_CFLAGS)
 CFLAGS	+= $(CFLAGS_libxentoollog)
+CFLAGS	+= $(CFLAGS_libxenevtchn)
 
 CTRL_LIB_OBJS := $(patsubst %.c,%.o,$(CTRL_SRCS-y))
 CTRL_PIC_OBJS := $(patsubst %.c,%.opic,$(CTRL_SRCS-y))
@@ -165,7 +167,7 @@ install: build
 	$(INSTALL_DATA) libxenctrl.a $(DESTDIR)$(libdir)
 	$(SYMLINK_SHLIB) libxenctrl.so.$(MAJOR).$(MINOR) $(DESTDIR)$(libdir)/libxenctrl.so.$(MAJOR)
 	$(SYMLINK_SHLIB) libxenctrl.so.$(MAJOR) $(DESTDIR)$(libdir)/libxenctrl.so
-	$(INSTALL_DATA) include/xenctrl.h include/xenctrlosdep.h $(DESTDIR)$(includedir)
+	$(INSTALL_DATA) include/xenctrl.h include/xenctrl_compat.h include/xenctrlosdep.h $(DESTDIR)$(includedir)
 	$(INSTALL_SHLIB) libxenguest.so.$(MAJOR).$(MINOR) $(DESTDIR)$(libdir)
 	$(INSTALL_DATA) libxenguest.a $(DESTDIR)$(libdir)
 	$(SYMLINK_SHLIB) libxenguest.so.$(MAJOR).$(MINOR) $(DESTDIR)$(libdir)/libxenguest.so.$(MAJOR)
@@ -208,7 +210,7 @@ libxenctrl.so.$(MAJOR): libxenctrl.so.$(MAJOR).$(MINOR)
 	$(SYMLINK_SHLIB) $< $@
 
 libxenctrl.so.$(MAJOR).$(MINOR): $(CTRL_PIC_OBJS)
-	$(CC) $(LDFLAGS) $(PTHREAD_LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenctrl.so.$(MAJOR) $(SHLIB_LDFLAGS) -o $@ $^ $(LDLIBS_libxentoollog) $(DLOPEN_LIBS) $(PTHREAD_LIBS) $(APPEND_LDFLAGS)
+	$(CC) $(LDFLAGS) $(PTHREAD_LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenctrl.so.$(MAJOR) $(SHLIB_LDFLAGS) -o $@ $^ $(LDLIBS_libxentoollog) $(LDLIBS_libxenevtchn) $(DLOPEN_LIBS) $(PTHREAD_LIBS) $(APPEND_LDFLAGS)
 
 # libxenguest
 
@@ -231,7 +233,7 @@ xc_dom_bzimageloader.opic: CFLAGS += $(call zlib-options,D)
 
 libxenguest.so.$(MAJOR).$(MINOR): COMPRESSION_LIBS = $(call zlib-options,l)
 libxenguest.so.$(MAJOR).$(MINOR): $(GUEST_PIC_OBJS) libxenctrl.so
-	$(CC) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenguest.so.$(MAJOR) $(SHLIB_LDFLAGS) -o $@ $(GUEST_PIC_OBJS) $(COMPRESSION_LIBS) -lz $(LDLIBS_libxenctrl) $(PTHREAD_LIBS) $(APPEND_LDFLAGS)
+	$(CC) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenguest.so.$(MAJOR) $(SHLIB_LDFLAGS) -o $@ $(GUEST_PIC_OBJS) $(COMPRESSION_LIBS) -lz $(LDLIBS_libxenevtchn) $(LDLIBS_libxenctrl) $(PTHREAD_LIBS) $(APPEND_LDFLAGS)
 
 xenctrl_osdep_ENOSYS.so: $(OSDEP_PIC_OBJS) libxenctrl.so
 	$(CC) $(LDFLAGS) $(SHLIB_LDFLAGS) -o $@ $(OSDEP_PIC_OBJS) $(LDLIBS_libxenctrl) $(APPEND_LDFLAGS)
diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h
index 53df9a9..d7ca161 100644
--- a/tools/libxc/include/xenctrl.h
+++ b/tools/libxc/include/xenctrl.h
@@ -118,7 +118,6 @@
  */
 
 typedef struct xc_interface_core xc_interface;
-typedef struct xenevtchn_handle xc_evtchn;
 typedef struct xc_interface_core xc_gnttab;
 typedef struct xc_interface_core xc_gntshr;
 
@@ -1094,7 +1093,6 @@ int xc_cpupool_movedomain(xc_interface *xch,
  */
 xc_cpumap_t xc_cpupool_freeinfo(xc_interface *xch);
 
-
 /*
  * EVENT CHANNEL FUNCTIONS
  *
@@ -1129,101 +1127,7 @@ int xc_evtchn_reset(xc_interface *xch,
 typedef struct evtchn_status xc_evtchn_status_t;
 int xc_evtchn_status(xc_interface *xch, xc_evtchn_status_t *status);
 
-/*
- * Return a handle to the event channel driver, or NULL on failure, in
- * which case errno will be set appropriately.
- *
- * Note:
- * After fork a child process must not use any opened xc evtchn
- * handle inherited from their parent. They must open a new handle if
- * they want to interact with xc.
- *
- * Before Xen pre-4.1 this function would sometimes report errors with perror.
- */
-xc_evtchn *xc_evtchn_open(xentoollog_logger *logger,
-                             unsigned open_flags);
 
-/*
- * Close a handle previously allocated with xc_evtchn_open().
- */
-int xc_evtchn_close(xc_evtchn *xce);
-
-/*
- * Return an fd that can be select()ed on.
- *
- * Note that due to bugs, setting this fd to non blocking may not
- * work: you would hope that it would result in xc_evtchn_pending
- * failing with EWOULDBLOCK if there are no events signaled, but in
- * fact it may block.  (Bug is present in at least Linux 3.12, and
- * perhaps on other platforms or later version.)
- *
- * To be safe, you must use poll() or select() before each call to
- * xc_evtchn_pending.  If you have multiple threads (or processes)
- * sharing a single xce handle this will not work, and there is no
- * straightforward workaround.  Please design your program some other
- * way.
- */
-int xc_evtchn_fd(xc_evtchn *xce);
-
-/*
- * Notify the given event channel. Returns -1 on failure, in which case
- * errno will be set appropriately.
- */
-int xc_evtchn_notify(xc_evtchn *xce, evtchn_port_t port);
-
-/*
- * Returns a new event port awaiting interdomain connection from the given
- * domain ID, or -1 on failure, in which case errno will be set appropriately.
- */
-evtchn_port_or_error_t
-xc_evtchn_bind_unbound_port(xc_evtchn *xce, int domid);
-
-/*
- * Returns a new event port bound to the remote port for the given domain ID,
- * or -1 on failure, in which case errno will be set appropriately.
- */
-evtchn_port_or_error_t
-xc_evtchn_bind_interdomain(xc_evtchn *xce, int domid,
-                           evtchn_port_t remote_port);
-
-/*
- * Bind an event channel to the given VIRQ. Returns the event channel bound to
- * the VIRQ, or -1 on failure, in which case errno will be set appropriately.
- */
-evtchn_port_or_error_t
-xc_evtchn_bind_virq(xc_evtchn *xce, unsigned int virq);
-
-/*
- * Unbind the given event channel. Returns -1 on failure, in which case errno
- * will be set appropriately.
- */
-int xc_evtchn_unbind(xc_evtchn *xce, evtchn_port_t port);
-
-/*
- * Return the next event channel to become pending, or -1 on failure, in which
- * case errno will be set appropriately.
- *
- * At the hypervisor level the event channel will have been masked,
- * and then cleared, by the underlying machinery (evtchn kernel
- * driver, or equivalent).  So if the event channel is signaled again
- * after it is returned here, it will be queued up, and delivered
- * again after you unmask it.  (See the documentation in the Xen
- * public header event_channel.h.)
- *
- * On receiving the notification from xc_evtchn_pending, you should
- * normally: check (by other means) what work needs doing; do the
- * necessary work (if any); unmask the event channel with
- * xc_evtchn_unmask (if you want to receive any further
- * notifications).
- */
-evtchn_port_or_error_t
-xc_evtchn_pending(xc_evtchn *xce);
-
-/*
- * Unmask the given event channel. Returns -1 on failure, in which case errno
- * will be set appropriately.
- */
-int xc_evtchn_unmask(xc_evtchn *xce, evtchn_port_t port);
 
 int xc_physdev_pci_access_modify(xc_interface *xch,
                                  uint32_t domid,
@@ -2797,6 +2701,9 @@ int xc_psr_cat_get_l3_info(xc_interface *xch, uint32_t socket,
                            uint32_t *cos_max, uint32_t *cbm_len);
 #endif
 
+/* Compat shims */
+#include "xenctrl_compat.h"
+
 #endif /* XENCTRL_H */
 
 /*
diff --git a/tools/libxc/include/xenctrl_compat.h b/tools/libxc/include/xenctrl_compat.h
new file mode 100644
index 0000000..48daeb2
--- /dev/null
+++ b/tools/libxc/include/xenctrl_compat.h
@@ -0,0 +1,48 @@
+/*
+ * Compat shims for use of 3rd party consumers of libxenctrl
+ * functionality which has been split into separate libraries.
+ *
+ * New code should use the separate libraries.
+ *
+ * Each interface must be opted-into separately by defining:
+ *
+ * XC_WANT_COMPAT_EVTCHN_API
+ *  - Functions relating to /dev/xen/evtchn
+ */
+#ifndef XENCTRL_COMPAT_H
+#define XENCTRL_COMPAT_H
+
+#ifdef XC_WANT_COMPAT_EVTCHN_API
+
+typedef struct xenevtchn_handle xc_evtchn;
+
+xc_evtchn *xc_evtchn_open(xentoollog_logger *logger,
+                             unsigned open_flags);
+int xc_evtchn_close(xc_evtchn *xce);
+int xc_evtchn_fd(xc_evtchn *xce);
+int xc_evtchn_notify(xc_evtchn *xce, evtchn_port_t port);
+evtchn_port_or_error_t
+xc_evtchn_bind_unbound_port(xc_evtchn *xce, int domid);
+evtchn_port_or_error_t
+xc_evtchn_bind_interdomain(xc_evtchn *xce, int domid,
+                           evtchn_port_t remote_port);
+evtchn_port_or_error_t
+xc_evtchn_bind_virq(xc_evtchn *xce, unsigned int virq);
+int xc_evtchn_unbind(xc_evtchn *xce, evtchn_port_t port);
+evtchn_port_or_error_t
+xc_evtchn_pending(xc_evtchn *xce);
+int xc_evtchn_unmask(xc_evtchn *xce, evtchn_port_t port);
+
+#endif /* XC_WANT_COMPAT_EVTCHN_API */
+
+#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxc/include/xenguest.h b/tools/libxc/include/xenguest.h
index e95af54..584ebdc 100644
--- a/tools/libxc/include/xenguest.h
+++ b/tools/libxc/include/xenguest.h
@@ -23,6 +23,8 @@
 #ifndef XENGUEST_H
 #define XENGUEST_H
 
+#include <xenevtchn.h>
+
 #define XC_NUMA_NO_NODE   (~0U)
 
 #define XCFLAGS_LIVE      (1 << 0)
@@ -288,18 +290,18 @@ int xc_hvm_build_target_mem(xc_interface *xch,
  * Sets *lockfd to -1.
  * Has deallocated everything even on error.
  */
-int xc_suspend_evtchn_release(xc_interface *xch, xc_evtchn *xce, int domid, int suspend_evtchn, int *lockfd);
+int xc_suspend_evtchn_release(xc_interface *xch, xenevtchn_handle *xce, int domid, int suspend_evtchn, int *lockfd);
 
 /**
  * This function eats the initial notification.
  * xce must not be used for anything else
  * See xc_suspend_evtchn_init_sane re lockfd.
  */
-int xc_suspend_evtchn_init_exclusive(xc_interface *xch, xc_evtchn *xce,
+int xc_suspend_evtchn_init_exclusive(xc_interface *xch, xenevtchn_handle *xce,
                                      int domid, int port, int *lockfd);
 
 /* xce must not be used for anything else */
-int xc_await_suspend(xc_interface *xch, xc_evtchn *xce, int suspend_evtchn);
+int xc_await_suspend(xc_interface *xch, xenevtchn_handle *xce, int suspend_evtchn);
 
 /**
  * The port will be signaled immediately after this call
@@ -308,7 +310,7 @@ int xc_await_suspend(xc_interface *xch, xc_evtchn *xce, int suspend_evtchn);
  * and fed to xc_suspend_evtchn_release.  (On error *lockfd is
  * undefined and xc_suspend_evtchn_release is not allowed.)
  */
-int xc_suspend_evtchn_init_sane(xc_interface *xch, xc_evtchn *xce,
+int xc_suspend_evtchn_init_sane(xc_interface *xch, xenevtchn_handle *xce,
                                 int domid, int port, int *lockfd);
 
 int xc_get_bit_size(xc_interface *xch,
diff --git a/tools/libxc/xc_evtchn_compat.c b/tools/libxc/xc_evtchn_compat.c
new file mode 100644
index 0000000..5d3e4ba
--- /dev/null
+++ b/tools/libxc/xc_evtchn_compat.c
@@ -0,0 +1,75 @@
+/*
+ * Compat shims for use of 3rd party consumers of libxenctrl xc_evtchn
+ * functionality which has been split into separate libraries.
+ */
+
+#include <xenevtchn.h>
+
+#define XC_WANT_COMPAT_EVTCHN_API
+#include "xenctrl.h"
+
+xc_evtchn *xc_evtchn_open(xentoollog_logger *logger,
+                          unsigned open_flags)
+{
+    return xenevtchn_open(logger, open_flags);
+}
+
+int xc_evtchn_close(xc_evtchn *xce)
+{
+    return xenevtchn_close(xce);
+}
+
+int xc_evtchn_fd(xc_evtchn *xce)
+{
+    return xenevtchn_fd(xce);
+}
+
+int xc_evtchn_notify(xc_evtchn *xce, evtchn_port_t port)
+{
+    return xenevtchn_notify(xce, port);
+}
+
+evtchn_port_or_error_t
+xc_evtchn_bind_unbound_port(xc_evtchn *xce, int domid)
+{
+    return xenevtchn_bind_unbound_port(xce, domid);
+}
+
+evtchn_port_or_error_t
+xc_evtchn_bind_interdomain(xc_evtchn *xce, int domid,
+                           evtchn_port_t remote_port)
+{
+    return xenevtchn_bind_interdomain(xce, domid, remote_port);
+}
+
+evtchn_port_or_error_t
+xc_evtchn_bind_virq(xc_evtchn *xce, unsigned int virq)
+{
+    return xenevtchn_bind_virq(xce, virq);
+}
+
+int xc_evtchn_unbind(xc_evtchn *xce, evtchn_port_t port)
+{
+    return xenevtchn_unbind(xce, port);
+}
+
+evtchn_port_or_error_t
+xc_evtchn_pending(xc_evtchn *xce)
+{
+    return xenevtchn_pending(xce);
+}
+
+int xc_evtchn_unmask(xc_evtchn *xce, evtchn_port_t port)
+{
+    return xenevtchn_unmask(xce, port);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxc/xc_freebsd_osdep.c b/tools/libxc/xc_freebsd_osdep.c
index 09d0693..d948b37 100644
--- a/tools/libxc/xc_freebsd_osdep.c
+++ b/tools/libxc/xc_freebsd_osdep.c
@@ -32,13 +32,11 @@
 #include <sys/ioctl.h>
 
 #include <xen/memory.h>
-#include <xen/sys/evtchn.h>
 
 #include "xenctrl.h"
 #include "xenctrlosdep.h"
 
 #define PRIVCMD_DEV     "/dev/xen/privcmd"
-#define EVTCHN_DEV      "/dev/xen/evtchn"
 
 #define PERROR(_m, _a...) xc_osdep_log(xch,XTL_ERROR,XC_INTERNAL_ERROR,_m \
                   " (%d = %s)", ## _a , errno, xc_strerror(xch, errno))
@@ -252,105 +250,6 @@ static struct xc_osdep_ops freebsd_privcmd_ops = {
     },
 };
 
-/*-------------------------- Evtchn device interface -------------------------*/
-int osdep_evtchn_open(xc_evtchn *xce)
-{
-    int fd = open(EVTCHN_DEV, O_RDWR);
-    if ( fd == -1 )
-        return -1;
-    xce->fd = fd;
-    return 0;
-}
-
-int osdep_evtchn_close(xc_evtchn *xce)
-{
-    if ( xce->fd == -1 )
-        return 0;
-
-    return close(xce->fd);
-}
-
-int xc_evtchn_fd(xc_evtchn *xce)
-{
-    return xce->fd;
-}
-
-/*------------------------------ Evtchn interface ----------------------------*/
-int xc_evtchn_notify(xc_evtchn *xce, evtchn_port_t port)
-{
-    int fd = xce->fd;
-    struct ioctl_evtchn_notify notify;
-
-    notify.port = port;
-
-    return ioctl(fd, IOCTL_EVTCHN_NOTIFY, &notify);
-}
-
-evtchn_port_or_error_t xc_evtchn_bind_unbound_port(xc_evtchn *xce, int domid)
-{
-    int ret, fd = xce->fd;
-    struct ioctl_evtchn_bind_unbound_port bind;
-
-    bind.remote_domain = domid;
-
-    ret = ioctl(fd, IOCTL_EVTCHN_BIND_UNBOUND_PORT, &bind);
-    return ( ret == 0 ) ? bind.port : ret;
-}
-
-evtchn_port_or_error_t
-xc_evtchn_bind_interdomain(xc_evtchn *xce, int domid, evtchn_port_t remote_port)
-{
-    int ret, fd = xce->fd;
-    struct ioctl_evtchn_bind_interdomain bind;
-
-    bind.remote_domain = domid;
-    bind.remote_port = remote_port;
-
-    ret = ioctl(fd, IOCTL_EVTCHN_BIND_INTERDOMAIN, &bind);
-    return ( ret == 0 ) ? bind.port : ret;
-}
-
-evtchn_port_or_error_t xc_evtchn_bind_virq(xc_evtchn *xce, unsigned int virq)
-{
-    int ret, fd = xce->fd;
-    struct ioctl_evtchn_bind_virq bind;
-
-    bind.virq = virq;
-
-    ret = ioctl(fd, IOCTL_EVTCHN_BIND_VIRQ, &bind);
-    return ( ret == 0 ) ? bind.port : ret;
-}
-
-int xc_evtchn_unbind(xc_evtchn *xce, evtchn_port_t port)
-{
-    int fd = xce->fd;
-    struct ioctl_evtchn_unbind unbind;
-
-    unbind.port = port;
-
-    return ioctl(fd, IOCTL_EVTCHN_UNBIND, &unbind);
-}
-
-evtchn_port_or_error_t xc_evtchn_pending(xc_evtchn *xce)
-{
-    int fd = xce->fd;
-    evtchn_port_t port;
-
-    if ( read(fd, &port, sizeof(port)) != sizeof(port) )
-        return -1;
-
-    return port;
-}
-
-int xc_evtchn_unmask(xc_evtchn *xce, evtchn_port_t port)
-{
-    int fd = xce->fd;
-
-    if ( write(fd, &port, sizeof(port)) != sizeof(port) )
-        return -1;
-    return 0;
-}
-
 /*---------------------------- FreeBSD interface -----------------------------*/
 static struct xc_osdep_ops *
 freebsd_osdep_init(xc_interface *xch, enum xc_osdep_type type)
diff --git a/tools/libxc/xc_linux_osdep.c b/tools/libxc/xc_linux_osdep.c
index 3c96c76..2230e44 100644
--- a/tools/libxc/xc_linux_osdep.c
+++ b/tools/libxc/xc_linux_osdep.c
@@ -32,7 +32,6 @@
 #include <sys/ioctl.h>
 
 #include <xen/memory.h>
-#include <xen/sys/evtchn.h>
 #include <xen/sys/gntdev.h>
 #include <xen/sys/gntalloc.h>
 
@@ -456,100 +455,6 @@ static struct xc_osdep_ops linux_privcmd_ops = {
 
 #define DEVXEN "/dev/xen/"
 
-int osdep_evtchn_open(xc_evtchn *xce)
-{
-    int fd = open(DEVXEN "evtchn", O_RDWR);
-    if ( fd == -1 )
-        return -1;
-    xce->fd = fd;
-    return 0;
-}
-
-int osdep_evtchn_close(xc_evtchn *xce)
-{
-    if ( xce->fd == -1 )
-        return 0;
-
-    return close(xce->fd);
-}
-
-int xc_evtchn_fd(xc_evtchn *xce)
-{
-    return xce->fd;
-}
-
-int xc_evtchn_notify(xc_evtchn *xce, evtchn_port_t port)
-{
-    int fd = xce->fd;
-    struct ioctl_evtchn_notify notify;
-
-    notify.port = port;
-
-    return ioctl(fd, IOCTL_EVTCHN_NOTIFY, &notify);
-}
-
-evtchn_port_or_error_t xc_evtchn_bind_unbound_port(xc_evtchn *xce, int domid)
-{
-    int fd = xce->fd;
-    struct ioctl_evtchn_bind_unbound_port bind;
-
-    bind.remote_domain = domid;
-
-    return ioctl(fd, IOCTL_EVTCHN_BIND_UNBOUND_PORT, &bind);
-}
-
-evtchn_port_or_error_t xc_evtchn_bind_interdomain(xc_evtchn *xce, int domid,
-                                                  evtchn_port_t remote_port)
-{
-    int fd = xce->fd;
-    struct ioctl_evtchn_bind_interdomain bind;
-
-    bind.remote_domain = domid;
-    bind.remote_port = remote_port;
-
-    return ioctl(fd, IOCTL_EVTCHN_BIND_INTERDOMAIN, &bind);
-}
-
-evtchn_port_or_error_t xc_evtchn_bind_virq(xc_evtchn *xce, unsigned int virq)
-{
-    int fd = xce->fd;
-    struct ioctl_evtchn_bind_virq bind;
-
-    bind.virq = virq;
-
-    return ioctl(fd, IOCTL_EVTCHN_BIND_VIRQ, &bind);
-}
-
-int xc_evtchn_unbind(xc_evtchn *xce, evtchn_port_t port)
-{
-    int fd = xce->fd;
-    struct ioctl_evtchn_unbind unbind;
-
-    unbind.port = port;
-
-    return ioctl(fd, IOCTL_EVTCHN_UNBIND, &unbind);
-}
-
-evtchn_port_or_error_t xc_evtchn_pending(xc_evtchn *xce)
-{
-    int fd = xce->fd;
-    evtchn_port_t port;
-
-    if ( read(fd, &port, sizeof(port)) != sizeof(port) )
-        return -1;
-
-    return port;
-}
-
-int xc_evtchn_unmask(xc_evtchn *xce, evtchn_port_t port)
-{
-    int fd = xce->fd;
-
-    if ( write(fd, &port, sizeof(port)) != sizeof(port) )
-        return -1;
-    return 0;
-}
-
 static xc_osdep_handle linux_gnttab_open(xc_gnttab *xcg)
 {
     int fd = open(DEVXEN "gntdev", O_RDWR);
diff --git a/tools/libxc/xc_minios.c b/tools/libxc/xc_minios.c
index e9c4d8b..7878cfa 100644
--- a/tools/libxc/xc_minios.c
+++ b/tools/libxc/xc_minios.c
@@ -20,14 +20,11 @@
  */
 
 #undef NDEBUG
-#include "xen-external/bsd-sys-queue.h"
 #include <mini-os/types.h>
 #include <mini-os/os.h>
 #include <mini-os/mm.h>
 #include <mini-os/lib.h>
 #include <mini-os/gntmap.h>
-#include <mini-os/events.h>
-#include <mini-os/wait.h>
 #include <sys/mman.h>
 
 #include <xen/memory.h>
@@ -42,13 +39,9 @@
 #include "xc_private.h"
 
 void minios_interface_close_fd(int fd);
-void minios_evtchn_close_fd(int fd);
 void minios_gnttab_close_fd(int fd);
 
 extern void minios_interface_close_fd(int fd);
-extern void minios_evtchn_close_fd(int fd);
-
-extern struct wait_queue_head event_queue;
 
 static xc_osdep_handle minios_privcmd_open(xc_interface *xch)
 {
@@ -198,220 +191,6 @@ static struct xc_osdep_ops minios_privcmd_ops = {
     },
 };
 
-
-/* XXX Note: This is not threadsafe */
-static struct evtchn_port_info* port_alloc(int fd) {
-    struct evtchn_port_info *port_info;
-    port_info = malloc(sizeof(struct evtchn_port_info));
-    if (port_info == NULL)
-        return NULL;
-    port_info->pending = 0;
-    port_info->port = -1;
-    port_info->bound = 0;
-
-    LIST_INSERT_HEAD(&files[fd].evtchn.ports, port_info, list);
-    return port_info;
-}
-
-static void port_dealloc(struct evtchn_port_info *port_info) {
-    if (port_info->bound)
-        unbind_evtchn(port_info->port);
-    LIST_REMOVE(port_info, list);
-    free(port_info);
-}
-
-int osdep_evtchn_open(xc_evtchn *xce)
-{
-    int fd = alloc_fd(FTYPE_EVTCHN);
-    if ( fd == -1 )
-        return -1;
-    LIST_INIT(&files[fd].evtchn.ports);
-    xce->fd = fd;
-    printf("evtchn_open() -> %d\n", fd);
-    return 0;
-}
-
-int osdep_evtchn_close(xc_evtchn *xce, xc_osdep_handle h)
-{
-    if ( xce->fd == -1 )
-        return 0;
-
-    return close(xce->fd);
-}
-
-void minios_evtchn_close_fd(int fd)
-{
-    struct evtchn_port_info *port_info, *tmp;
-    LIST_FOREACH_SAFE(port_info, &files[fd].evtchn.ports, list, tmp)
-        port_dealloc(port_info);
-
-    files[fd].type = FTYPE_NONE;
-}
-
-int xc_evtchn_fd(xc_evtchn *xce)
-{
-    return xce->fd;
-}
-
-int xc_evtchn_notify(xc_evtchn *xce, evtchn_port_t port)
-{
-    int ret;
-
-    ret = notify_remote_via_evtchn(port);
-
-    if (ret < 0) {
-	errno = -ret;
-	ret = -1;
-    }
-    return ret;
-}
-
-static void evtchn_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
-{
-    int fd = (int)(intptr_t)data;
-    struct evtchn_port_info *port_info;
-    assert(files[fd].type == FTYPE_EVTCHN);
-    mask_evtchn(port);
-    LIST_FOREACH(port_info, &files[fd].evtchn.ports, list) {
-        if (port_info->port == port)
-            goto found;
-    }
-    printk("Unknown port for handle %d\n", fd);
-    return;
-
- found:
-    port_info->pending = 1;
-    files[fd].read = 1;
-    wake_up(&event_queue);
-}
-
-evtchn_port_or_error_t xc_evtchn_bind_unbound_port(xc_evtchn *xce, int domid)
-{
-    int fd = xce->fd;
-    struct evtchn_port_info *port_info;
-    int ret;
-    evtchn_port_t port;
-
-    assert(get_current() == main_thread);
-    port_info = port_alloc(fd);
-    if (port_info == NULL)
-	return -1;
-
-    printf("xc_evtchn_bind_unbound_port(%d)", domid);
-    ret = evtchn_alloc_unbound(domid, evtchn_handler, (void*)(intptr_t)fd, &port);
-    printf(" = %d\n", ret);
-
-    if (ret < 0) {
-	port_dealloc(port_info);
-	errno = -ret;
-	return -1;
-    }
-    port_info->bound = 1;
-    port_info->port = port;
-    unmask_evtchn(port);
-    return port;
-}
-
-evtchn_port_or_error_t xc_evtchn_bind_interdomain(xc_evtchn *xce, int domid,
-                                                  evtchn_port_t remote_port)
-{
-    int fd = xce->fd;
-    struct evtchn_port_info *port_info;
-    evtchn_port_t local_port;
-    int ret;
-
-    assert(get_current() == main_thread);
-    port_info = port_alloc(fd);
-    if (port_info == NULL)
-	return -1;
-
-    printf("xc_evtchn_bind_interdomain(%d, %"PRId32")", domid, remote_port);
-    ret = evtchn_bind_interdomain(domid, remote_port, evtchn_handler, (void*)(intptr_t)fd, &local_port);
-    printf(" = %d\n", ret);
-
-    if (ret < 0) {
-	port_dealloc(port_info);
-	errno = -ret;
-	return -1;
-    }
-    port_info->bound = 1;
-    port_info->port = local_port;
-    unmask_evtchn(local_port);
-    return local_port;
-}
-
-int xc_evtchn_unbind(xc_evtchn *xce, evtchn_port_t port)
-{
-    int fd = xce->fd;
-    struct evtchn_port_info *port_info;
-
-    LIST_FOREACH(port_info, &files[fd].evtchn.ports, list) {
-        if (port_info->port == port) {
-            port_dealloc(port_info);
-            return 0;
-        }
-    }
-    printf("Warning: couldn't find port %"PRId32" for xc handle %x\n", port, fd);
-    errno = EINVAL;
-    return -1;
-}
-
-evtchn_port_or_error_t xc_evtchn_bind_virq(xc_evtchn *xce, unsigned int virq)
-{
-    int fd = xce->fd;
-    struct evtchn_port_info *port_info;
-    evtchn_port_t port;
-
-    assert(get_current() == main_thread);
-    port_info = port_alloc(fd);
-    if (port_info == NULL)
-	return -1;
-
-    printf("xc_evtchn_bind_virq(%d)", virq);
-    port = bind_virq(virq, evtchn_handler, (void*)(intptr_t)fd);
-
-    if (port < 0) {
-	port_dealloc(port_info);
-	errno = -port;
-	return -1;
-    }
-    port_info->bound = 1;
-    port_info->port = port;
-    unmask_evtchn(port);
-    return port;
-}
-
-evtchn_port_or_error_t xc_evtchn_pending(xc_evtchn *xce)
-{
-    int fd = xce->fd;
-    struct evtchn_port_info *port_info;
-    unsigned long flags;
-    evtchn_port_t ret = -1;
-
-    local_irq_save(flags);
-    files[fd].read = 0;
-
-    LIST_FOREACH(port_info, &files[fd].evtchn.ports, list) {
-        if (port_info->port != -1 && port_info->pending) {
-            if (ret == -1) {
-                ret = port_info->port;
-                port_info->pending = 0;
-            } else {
-                files[fd].read = 1;
-                break;
-            }
-        }
-    }
-    local_irq_restore(flags);
-    return ret;
-}
-
-int xc_evtchn_unmask(xc_evtchn *xce, evtchn_port_t port)
-{
-    unmask_evtchn(port);
-    return 0;
-}
-
 /* Optionally flush file to disk and discard page cache */
 void discard_file_cache(xc_interface *xch, int fd, int flush)
 {
diff --git a/tools/libxc/xc_netbsd.c b/tools/libxc/xc_netbsd.c
index f9bc100..48fd5d7 100644
--- a/tools/libxc/xc_netbsd.c
+++ b/tools/libxc/xc_netbsd.c
@@ -20,7 +20,6 @@
 
 #include "xc_private.h"
 
-#include <xen/sys/evtchn.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <malloc.h>
@@ -224,114 +223,6 @@ static struct xc_osdep_ops netbsd_privcmd_ops = {
     },
 };
 
-#define EVTCHN_DEV_NAME  "/dev/xenevt"
-
-int osdep_evtchn_open(xc_evtchn *xce)
-{
-    int fd = open(EVTCHN_DEV_NAME, O_NONBLOCK|O_RDWR);
-    if ( fd == -1 )
-        return -1;
-    xce->fd = fd;
-    return 0;
-}
-
-int osdep_evtchn_close(xc_evtchn *xce, xc_osdep_handle h)
-{
-    if ( xce->fd == -1 )
-        return 0;
-
-    return close(xce->fd);
-}
-
-int xc_evtchn_fd(xc_evtchn *xce)
-{
-    return xce->fd;
-}
-
-int xc_evtchn_notify(xc_evtchn *xce, evtchn_port_t port)
-{
-    int fd = xce->fd;
-    struct ioctl_evtchn_notify notify;
-
-    notify.port = port;
-
-    return ioctl(fd, IOCTL_EVTCHN_NOTIFY, &notify);
-}
-
-evtchn_port_or_error_t xc_evtchn_bind_unbound_port(xc_evtchn * xce, int domid)
-{
-    int fd = xce->fd;
-    struct ioctl_evtchn_bind_unbound_port bind;
-    int ret;
-
-    bind.remote_domain = domid;
-
-    ret = ioctl(fd, IOCTL_EVTCHN_BIND_UNBOUND_PORT, &bind);
-    if (ret == 0)
-	return bind.port;
-    else
-	return -1;
-}
-
-evtchn_port_or_error_t xc_evtchn_bind_interdomain(xc_evtchn *xce, int domid,
-                                                  evtchn_port_t remote_port)
-{
-    int fd = xce->fd;
-    struct ioctl_evtchn_bind_interdomain bind;
-    int ret;
-
-    bind.remote_domain = domid;
-    bind.remote_port = remote_port;
-
-    ret = ioctl(fd, IOCTL_EVTCHN_BIND_INTERDOMAIN, &bind);
-    if (ret == 0)
-	return bind.port;
-    else
-	return -1;
-}
-
-int xc_evtchn_unbind(xc_evtchn *xce, evtchn_port_t port)
-{
-    int fd = xce->fd;
-    struct ioctl_evtchn_unbind unbind;
-
-    unbind.port = port;
-
-    return ioctl(fd, IOCTL_EVTCHN_UNBIND, &unbind);
-}
-
-evtchn_port_or_error_t xc_evtchn_bind_virq(xc_evtchn *xce, unsigned int virq)
-{
-    int fd = xce->fd;
-    struct ioctl_evtchn_bind_virq bind;
-    int err;
-
-    bind.virq = virq;
-
-    err = ioctl(fd, IOCTL_EVTCHN_BIND_VIRQ, &bind);
-    if (err)
-	return -1;
-    else
-	return bind.port;
-}
-
-evtchn_port_or_error_t xc_evtchn_pending(xc_evtchn *xce)
-{
-    int fd = xce->fd;
-    evtchn_port_t port;
-
-    if ( read_exact(fd, (char *)&port, sizeof(port)) == -1 )
-        return -1;
-
-    return port;
-}
-
-int xc_evtchn_unmask(xc_evtchn *xce, evtchn_port_t port)
-{
-    int fd = xce->fd;
-    return write_exact(fd, (char *)&port, sizeof(port));
-}
-
 /* Optionally flush file to disk and discard page cache */
 void discard_file_cache(xc_interface *xch, int fd, int flush) 
 {
diff --git a/tools/libxc/xc_private.c b/tools/libxc/xc_private.c
index 9f0ada7..375430c 100644
--- a/tools/libxc/xc_private.c
+++ b/tools/libxc/xc_private.c
@@ -252,46 +252,6 @@ int do_xen_hypercall(xc_interface *xch, privcmd_hypercall_t *hypercall)
     return xch->ops->u.privcmd.hypercall(xch, xch->ops_handle, hypercall);
 }
 
-xc_evtchn *xc_evtchn_open(xentoollog_logger *logger, unsigned open_flags)
-{
-    xc_evtchn *xce = malloc(sizeof(*xce));
-    int rc;
-
-    if (!xce) return NULL;
-
-    xce->fd = -1;
-    xce->logger = logger;
-    xce->logger_tofree  = NULL;
-
-    if (!xce->logger) {
-        xce->logger = xce->logger_tofree =
-            (xentoollog_logger*)
-            xtl_createlogger_stdiostream(stderr, XTL_PROGRESS, 0);
-        if (!xce->logger) goto err;
-    }
-
-    rc = osdep_evtchn_open(xce);
-    if ( rc  < 0 ) goto err;
-
-    return xce;
-
-err:
-    osdep_evtchn_close(xce);
-    xtl_logger_destroy(xce->logger_tofree);
-    free(xce);
-    return NULL;
-}
-
-int xc_evtchn_close(xc_evtchn *xce)
-{
-    int rc;
-
-    rc = osdep_evtchn_close(xce);
-    xtl_logger_destroy(xce->logger_tofree);
-    free(xce);
-    return rc;
-}
-
 xc_gnttab *xc_gnttab_open(xentoollog_logger *logger,
                              unsigned open_flags)
 {
diff --git a/tools/libxc/xc_private.h b/tools/libxc/xc_private.h
index 4c66766..61f2f45 100644
--- a/tools/libxc/xc_private.h
+++ b/tools/libxc/xc_private.h
@@ -124,13 +124,6 @@ struct xc_interface_core {
     xc_osdep_handle  ops_handle; /* opaque data for xc_osdep_ops */
 };
 
-struct xenevtchn_handle {
-    xentoollog_logger *logger, *logger_tofree;
-    int fd;
-};
-int osdep_evtchn_open(xc_evtchn *xce);
-int osdep_evtchn_close(xc_evtchn *xce);
-
 void xc_report_error(xc_interface *xch, int code, const char *fmt, ...)
     __attribute__((format(printf,3,4)));
 void xc_reportv(xc_interface *xch, xentoollog_logger *lg, xentoollog_level,
diff --git a/tools/libxc/xc_solaris.c b/tools/libxc/xc_solaris.c
index 8867d97..182bd7d 100644
--- a/tools/libxc/xc_solaris.c
+++ b/tools/libxc/xc_solaris.c
@@ -21,7 +21,6 @@
 #include "xc_private.h"
 
 #include <xen/memory.h>
-#include <xen/sys/evtchn.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <malloc.h>
@@ -195,102 +194,6 @@ static struct xc_osdep_ops solaris_privcmd_ops = {
     },
 };
 
-int osdep_evtchn_open(xc_evtchn *xce)
-{
-    int fd;
-
-    if ( (fd = open("/dev/xen/evtchn", O_RDWR)) == -1 )
-    {
-        PERROR("Could not open event channel interface");
-        return -1;
-    }
-
-    xce->fd = fd;
-    return 0;
-}
-
-int osdep_evtchn_close(xc_evtchn *xce)
-{
-    if ( xce->fd == -1 )
-        return 0;
-
-    return close(xce->fd);
-}
-
-int xc_evtchn_fd(xc_evtchn *xce)
-{
-    return xce->fd;
-}
-
-int xc_evtchn_notify(xc_evtchn *xce, evtchn_port_t port)
-{
-    int fd = xce->fd;
-    struct ioctl_evtchn_notify notify;
-
-    notify.port = port;
-
-    return ioctl(fd, IOCTL_EVTCHN_NOTIFY, &notify);
-}
-
-evtchn_port_or_error_t xc_evtchn_bind_unbound_port(xc_evtchn *xce, int domid)
-{
-    int fd = xce->fd;
-    struct ioctl_evtchn_bind_unbound_port bind;
-
-    bind.remote_domain = domid;
-
-    return ioctl(fd, IOCTL_EVTCHN_BIND_UNBOUND_PORT, &bind);
-}
-
-evtchn_port_or_error_t xc_evtchn_bind_interdomain(xc_evtchn *xce, int domid,
-                                                  evtchn_port_t remote_port)
-{
-    int fd = xce->fd;
-    struct ioctl_evtchn_bind_interdomain bind;
-
-    bind.remote_domain = domid;
-    bind.remote_port = remote_port;
-
-    return ioctl(fd, IOCTL_EVTCHN_BIND_INTERDOMAIN, &bind);
-}
-
-evtchn_port_or_error_t xc_evtchn_bind_virq(xc_evtchn *xce, unsigned int virq)
-{
-    int fd = xce->fd;
-    struct ioctl_evtchn_bind_virq bind;
-
-    bind.virq = virq;
-
-    return ioctl(fd, IOCTL_EVTCHN_BIND_VIRQ, &bind);
-}
-
-int xc_evtchn_unbind(xc_evtchn *xce, evtchn_port_t port)
-{
-    int fd = xce->fd;
-    struct ioctl_evtchn_unbind unbind;
-
-    unbind.port = port;
-
-    return ioctl(fd, IOCTL_EVTCHN_UNBIND, &unbind);
-}
-
-evtchn_port_or_error_t xc_evtchn_pending(xc_evtchn *xce)
-{
-    int fd = xce->fd;
-    evtchn_port_t port;
-
-    if ( read_exact(fd, (char *)&port, sizeof(port)) == -1 )
-        return -1;
-
-    return port;
-}
-
-int xc_evtchn_unmask(xc_evtchn *xce, evtchn_port_t port)
-{
-    int fd = xce->fd;
-    return write_exact(fd, (char *)&port, sizeof(port));
-}
-
 /* Optionally flush file to disk and discard page cache */
 void discard_file_cache(xc_interface *xch, int fd, int flush) 
 {
diff --git a/tools/libxc/xc_suspend.c b/tools/libxc/xc_suspend.c
index e22f4ac..139edb4 100644
--- a/tools/libxc/xc_suspend.c
+++ b/tools/libxc/xc_suspend.c
@@ -17,6 +17,8 @@
 #include <unistd.h>
 #include <fcntl.h>
 
+#include <xenevtchn.h>
+
 #include "xc_private.h"
 #include "xenguest.h"
 
@@ -125,12 +127,12 @@ static int unlock_suspend_event(xc_interface *xch, int domid, int *lockfd)
     return -1;
 }
 
-int xc_await_suspend(xc_interface *xch, xc_evtchn *xce, int suspend_evtchn)
+int xc_await_suspend(xc_interface *xch, xenevtchn_handle *xce, int suspend_evtchn)
 {
     int rc;
 
     do {
-        rc = xc_evtchn_pending(xce);
+        rc = xenevtchn_pending(xce);
         if (rc < 0) {
             ERROR("error polling suspend notification channel: %d", rc);
             return -1;
@@ -138,7 +140,7 @@ int xc_await_suspend(xc_interface *xch, xc_evtchn *xce, int suspend_evtchn)
     } while (rc != suspend_evtchn);
 
     /* harmless for one-off suspend */
-    if (xc_evtchn_unmask(xce, suspend_evtchn) < 0)
+    if (xenevtchn_unmask(xce, suspend_evtchn) < 0)
         ERROR("failed to unmask suspend notification channel: %d", rc);
 
     return 0;
@@ -146,16 +148,16 @@ int xc_await_suspend(xc_interface *xch, xc_evtchn *xce, int suspend_evtchn)
 
 /* Internal callers are allowed to call this with suspend_evtchn<0
  * but *lockfd>0. */
-int xc_suspend_evtchn_release(xc_interface *xch, xc_evtchn *xce,
+int xc_suspend_evtchn_release(xc_interface *xch, xenevtchn_handle *xce,
                               int domid, int suspend_evtchn, int *lockfd)
 {
     if (suspend_evtchn >= 0)
-        xc_evtchn_unbind(xce, suspend_evtchn);
+        xenevtchn_unbind(xce, suspend_evtchn);
 
     return unlock_suspend_event(xch, domid, lockfd);
 }
 
-int xc_suspend_evtchn_init_sane(xc_interface *xch, xc_evtchn *xce,
+int xc_suspend_evtchn_init_sane(xc_interface *xch, xenevtchn_handle *xce,
                                 int domid, int port, int *lockfd)
 {
     int rc, suspend_evtchn = -1;
@@ -165,7 +167,7 @@ int xc_suspend_evtchn_init_sane(xc_interface *xch, xc_evtchn *xce,
         goto cleanup;
     }
 
-    suspend_evtchn = xc_evtchn_bind_interdomain(xce, domid, port);
+    suspend_evtchn = xenevtchn_bind_interdomain(xce, domid, port);
     if (suspend_evtchn < 0) {
         ERROR("failed to bind suspend event channel: %d", suspend_evtchn);
         goto cleanup;
@@ -185,7 +187,7 @@ cleanup:
     return -1;
 }
 
-int xc_suspend_evtchn_init_exclusive(xc_interface *xch, xc_evtchn *xce,
+int xc_suspend_evtchn_init_exclusive(xc_interface *xch, xenevtchn_handle *xce,
                                      int domid, int port, int *lockfd)
 {
     int suspend_evtchn;
diff --git a/tools/libxenevtchn/Makefile b/tools/libxenevtchn/Makefile
new file mode 100644
index 0000000..c3ea3c2
--- /dev/null
+++ b/tools/libxenevtchn/Makefile
@@ -0,0 +1,65 @@
+XEN_ROOT = $(CURDIR)/../..
+include $(XEN_ROOT)/tools/Rules.mk
+
+MAJOR    = 1
+MINOR    = 0
+SHLIB_LDFLAGS += -Wl,--version-script=libxenevtchn.map
+
+CFLAGS   += -Werror -Wmissing-prototypes
+CFLAGS   += -I./include $(CFLAGS_xeninclude)
+CFLAGS   += $(CFLAGS_libxentoollog)
+
+SRCS-y                 += core.c
+SRCS-$(CONFIG_Linux)   += linux.c
+SRCS-$(CONFIG_FreeBSD) += freebsd.c
+SRCS-$(CONFIG_SunOS)   += solaris.c
+SRCS-$(CONFIG_NetBSD)  += netbsd.c
+SRCS-$(CONFIG_MiniOS)  += minios.c
+
+LIB_OBJS := $(patsubst %.c,%.o,$(SRCS-y))
+PIC_OBJS := $(patsubst %.c,%.opic,$(SRCS-y))
+
+LIB := libxenevtchn.a
+ifneq ($(nosharedlibs),y)
+LIB += libxenevtchn.so
+endif
+
+.PHONY: all
+all: build
+
+.PHONY: build
+build:
+	$(MAKE) libs
+
+.PHONY: libs
+libs: $(LIB)
+
+
+libxenevtchn.a: $(LIB_OBJS)
+	$(AR) rc $@ $^
+
+libxenevtchn.so: libxenevtchn.so.$(MAJOR)
+	$(SYMLINK_SHLIB) $< $@
+libxenevtchn.so.$(MAJOR): libxenevtchn.so.$(MAJOR).$(MINOR)
+	$(SYMLINK_SHLIB) $< $@
+
+libxenevtchn.so.$(MAJOR).$(MINOR): $(PIC_OBJS) libxenevtchn.map
+	$(CC) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenevtchn.so.$(MAJOR) $(SHLIB_LDFLAGS) -o $@ $(PIC_OBJS) $(LDLIBS_libxentoollog) $(APPEND_LDFLAGS)
+
+.PHONY: install
+install: build
+	$(INSTALL_DIR) $(DESTDIR)$(libdir)
+	$(INSTALL_DIR) $(DESTDIR)$(includedir)
+	$(INSTALL_SHLIB) libxenevtchn.so.$(MAJOR).$(MINOR) $(DESTDIR)$(libdir)
+	$(INSTALL_DATA) libxenevtchn.a $(DESTDIR)$(libdir)
+	$(SYMLINK_SHLIB) libxenevtchn.so.$(MAJOR).$(MINOR) $(DESTDIR)$(libdir)/libxenevtchn.so.$(MAJOR)
+	$(SYMLINK_SHLIB) libxenevtchn.so.$(MAJOR) $(DESTDIR)$(libdir)/libxenevtchn.so
+	$(INSTALL_DATA) include/xenevtchn.h $(DESTDIR)$(includedir)
+
+.PHONY: TAGS
+TAGS:
+	etags -t *.c *.h
+
+.PHONY: clean
+clean:
+	rm -rf *.rpm $(LIB) *~ $(DEPS) $(LIB_OBJS) $(PIC_OBJS)
diff --git a/tools/libxenevtchn/core.c b/tools/libxenevtchn/core.c
new file mode 100644
index 0000000..68616c9
--- /dev/null
+++ b/tools/libxenevtchn/core.c
@@ -0,0 +1,70 @@
+/*
+ * This library 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 of the License.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "private.h"
+
+xenevtchn_handle *xenevtchn_open(xentoollog_logger *logger, unsigned open_flags)
+{
+    xenevtchn_handle *xce = malloc(sizeof(*xce));
+    int rc;
+
+    if (!xce) return NULL;
+
+    xce->fd = -1;
+    xce->logger = logger;
+    xce->logger_tofree  = NULL;
+
+    if (!xce->logger) {
+        xce->logger = xce->logger_tofree =
+            (xentoollog_logger*)
+            xtl_createlogger_stdiostream(stderr, XTL_PROGRESS, 0);
+        if (!xce->logger) goto err;
+    }
+
+    rc = osdep_evtchn_open(xce);
+    if ( rc  < 0 ) goto err;
+
+    return xce;
+
+err:
+    osdep_evtchn_close(xce);
+    xtl_logger_destroy(xce->logger_tofree);
+    free(xce);
+    return NULL;
+}
+
+int xenevtchn_close(xenevtchn_handle *xce)
+{
+    int rc;
+
+    rc = osdep_evtchn_close(xce);
+    xtl_logger_destroy(xce->logger_tofree);
+    free(xce);
+    return rc;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxenevtchn/freebsd.c b/tools/libxenevtchn/freebsd.c
new file mode 100644
index 0000000..9b99fc0
--- /dev/null
+++ b/tools/libxenevtchn/freebsd.c
@@ -0,0 +1,135 @@
+ /******************************************************************************
+ *
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * This library 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 of the License.
+ *
+ * This library 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.
+ *
+ * Split off from xc_freebsd_osdep.c
+ */
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <sys/ioctl.h>
+
+#include <xen/sys/evtchn.h>
+
+#include "private.h"
+
+#define EVTCHN_DEV      "/dev/xen/evtchn"
+
+int osdep_evtchn_open(xenevtchn_handle *xce)
+{
+    int fd = open(EVTCHN_DEV, O_RDWR);
+    if ( fd == -1 )
+        return -1;
+    xce->fd = fd;
+    return 0;
+}
+
+int osdep_evtchn_close(xenevtchn_handle *xce)
+{
+    if ( xce->fd == -1 )
+        return 0;
+
+    return close(xce->fd);
+}
+
+int xenevtchn_fd(xenevtchn_handle *xce)
+{
+    return xce->fd;
+}
+
+int xenevtchn_notify(xenevtchn_handle *xce, evtchn_port_t port)
+{
+    int fd = xce->fd;
+    struct ioctl_evtchn_notify notify;
+
+    notify.port = port;
+
+    return ioctl(fd, IOCTL_EVTCHN_NOTIFY, &notify);
+}
+
+evtchn_port_or_error_t xenevtchn_bind_unbound_port(xenevtchn_handle *xce, int domid)
+{
+    int ret, fd = xce->fd;
+    struct ioctl_evtchn_bind_unbound_port bind;
+
+    bind.remote_domain = domid;
+
+    ret = ioctl(fd, IOCTL_EVTCHN_BIND_UNBOUND_PORT, &bind);
+    return ( ret == 0 ) ? bind.port : ret;
+}
+
+evtchn_port_or_error_t
+xenevtchn_bind_interdomain(xenevtchn_handle *xce, int domid, evtchn_port_t remote_port)
+{
+    int ret, fd = xce->fd;
+    struct ioctl_evtchn_bind_interdomain bind;
+
+    bind.remote_domain = domid;
+    bind.remote_port = remote_port;
+
+    ret = ioctl(fd, IOCTL_EVTCHN_BIND_INTERDOMAIN, &bind);
+    return ( ret == 0 ) ? bind.port : ret;
+}
+
+evtchn_port_or_error_t xenevtchn_bind_virq(xenevtchn_handle *xce, unsigned int virq)
+{
+    int ret, fd = xce->fd;
+    struct ioctl_evtchn_bind_virq bind;
+
+    bind.virq = virq;
+
+    ret = ioctl(fd, IOCTL_EVTCHN_BIND_VIRQ, &bind);
+    return ( ret == 0 ) ? bind.port : ret;
+}
+
+int xenevtchn_unbind(xenevtchn_handle *xce, evtchn_port_t port)
+{
+    int fd = xce->fd;
+    struct ioctl_evtchn_unbind unbind;
+
+    unbind.port = port;
+
+    return ioctl(fd, IOCTL_EVTCHN_UNBIND, &unbind);
+}
+
+evtchn_port_or_error_t xenevtchn_pending(xenevtchn_handle *xce)
+{
+    int fd = xce->fd;
+    evtchn_port_t port;
+
+    if ( read(fd, &port, sizeof(port)) != sizeof(port) )
+        return -1;
+
+    return port;
+}
+
+int xenevtchn_unmask(xenevtchn_handle *xce, evtchn_port_t port)
+{
+    int fd = xce->fd;
+
+    if ( write(fd, &port, sizeof(port)) != sizeof(port) )
+        return -1;
+    return 0;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxenevtchn/include/xenevtchn.h b/tools/libxenevtchn/include/xenevtchn.h
new file mode 100644
index 0000000..41928f6
--- /dev/null
+++ b/tools/libxenevtchn/include/xenevtchn.h
@@ -0,0 +1,147 @@
+/*
+ * This library 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 of the License.
+ *
+ * This library 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.
+ *
+ * Split off from:
+ * xenctrl.h
+ *
+ * A library for low-level access to the Xen control interfaces.
+ *
+ * Copyright (c) 2003-2004, K A Fraser.
+ */
+
+#ifndef XENEVTCHN_H
+#define XENEVTCHN_H
+
+#include <stdint.h>
+
+#include <xen/event_channel.h>
+
+/* A port identifier is guaranteed to fit in 31 bits. */
+typedef int evtchn_port_or_error_t;
+
+typedef struct xenevtchn_handle xenevtchn_handle;
+
+/* Callers who don't care don't need to #include <xentoollog.h> */
+typedef struct xentoollog_logger xentoollog_logger;
+
+/*
+ * EVENT CHANNEL FUNCTIONS
+ *
+ * None of these do any logging.
+ */
+
+/*
+ * Return a handle to the event channel driver, or NULL on failure, in
+ * which case errno will be set appropriately.
+ *
+ * Note:
+ * After fork a child process must not use any opened xc evtchn
+ * handle inherited from their parent. They must open a new handle if
+ * they want to interact with xc.
+ *
+ * Before Xen pre-4.1 this function would sometimes report errors with perror.
+ */
+/* Currently no flags are defined */
+xenevtchn_handle *xenevtchn_open(xentoollog_logger *logger, unsigned open_flags);
+
+/*
+ * Close a handle previously allocated with xenevtchn_open().
+ */
+int xenevtchn_close(xenevtchn_handle *xce);
+
+/*
+ * Return an fd that can be select()ed on.
+ *
+ * Note that due to bugs, setting this fd to non blocking may not
+ * work: you would hope that it would result in xenevtchn_pending
+ * failing with EWOULDBLOCK if there are no events signaled, but in
+ * fact it may block.  (Bug is present in at least Linux 3.12, and
+ * perhaps on other platforms or later version.)
+ *
+ * To be safe, you must use poll() or select() before each call to
+ * xenevtchn_pending.  If you have multiple threads (or processes)
+ * sharing a single xce handle this will not work, and there is no
+ * straightforward workaround.  Please design your program some other
+ * way.
+ */
+int xenevtchn_fd(xenevtchn_handle *xce);
+
+/*
+ * Notify the given event channel. Returns -1 on failure, in which case
+ * errno will be set appropriately.
+ */
+int xenevtchn_notify(xenevtchn_handle *xce, evtchn_port_t port);
+
+/*
+ * Returns a new event port awaiting interdomain connection from the given
+ * domain ID, or -1 on failure, in which case errno will be set appropriately.
+ */
+evtchn_port_or_error_t
+xenevtchn_bind_unbound_port(xenevtchn_handle *xce, int domid);
+
+/*
+ * Returns a new event port bound to the remote port for the given domain ID,
+ * or -1 on failure, in which case errno will be set appropriately.
+ */
+evtchn_port_or_error_t
+xenevtchn_bind_interdomain(xenevtchn_handle *xce, int domid,
+                           evtchn_port_t remote_port);
+
+/*
+ * Bind an event channel to the given VIRQ. Returns the event channel bound to
+ * the VIRQ, or -1 on failure, in which case errno will be set appropriately.
+ */
+evtchn_port_or_error_t
+xenevtchn_bind_virq(xenevtchn_handle *xce, unsigned int virq);
+
+/*
+ * Unbind the given event channel. Returns -1 on failure, in which case errno
+ * will be set appropriately.
+ */
+int xenevtchn_unbind(xenevtchn_handle *xce, evtchn_port_t port);
+
+/*
+ * Return the next event channel to become pending, or -1 on failure, in which
+ * case errno will be set appropriately.
+ *
+ * At the hypervisor level the event channel will have been masked,
+ * and then cleared, by the underlying machinery (evtchn kernel
+ * driver, or equivalent).  So if the event channel is signaled again
+ * after it is returned here, it will be queued up, and delivered
+ * again after you unmask it.  (See the documentation in the Xen
+ * public header event_channel.h.)
+ *
+ * On receiving the notification from xenevtchn_pending, you should
+ * normally: check (by other means) what work needs doing; do the
+ * necessary work (if any); unmask the event channel with
+ * xenevtchn_unmask (if you want to receive any further
+ * notifications).
+ */
+evtchn_port_or_error_t
+xenevtchn_pending(xenevtchn_handle *xce);
+
+/*
+ * Unmask the given event channel. Returns -1 on failure, in which case errno
+ * will be set appropriately.
+ */
+int xenevtchn_unmask(xenevtchn_handle *xce, evtchn_port_t port);
+
+#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxenevtchn/libxenevtchn.map b/tools/libxenevtchn/libxenevtchn.map
new file mode 100644
index 0000000..1437940
--- /dev/null
+++ b/tools/libxenevtchn/libxenevtchn.map
@@ -0,0 +1,14 @@
+VERS_1.0 {
+	global:
+		xenevtchn_fd;
+		xenevtchn_bind_unbound_port;
+		xenevtchn_unbind;
+		xenevtchn_unmask;
+		xenevtchn_notify;
+		xenevtchn_bind_interdomain;
+		xenevtchn_bind_virq;
+		xenevtchn_open;
+		xenevtchn_close;
+		xenevtchn_pending;
+	local: *; /* Do not expose anything by default */
+};
diff --git a/tools/libxenevtchn/linux.c b/tools/libxenevtchn/linux.c
new file mode 100644
index 0000000..185244c
--- /dev/null
+++ b/tools/libxenevtchn/linux.c
@@ -0,0 +1,133 @@
+/*
+ * This library 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 of the License.
+ *
+ * This library 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.
+ *
+ * Split out from xc_linus_osdep.c:
+ *
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <sys/ioctl.h>
+
+#include <xen/sys/evtchn.h>
+
+#include "private.h"
+
+int osdep_evtchn_open(xenevtchn_handle *xce)
+{
+    int fd = open("/dev/xen/evtchn", O_RDWR);
+    if ( fd == -1 )
+        return -1;
+    xce->fd = fd;
+    return 0;
+}
+
+int osdep_evtchn_close(xenevtchn_handle *xce)
+{
+    if ( xce->fd == -1 )
+        return 0;
+
+    return close(xce->fd);
+}
+
+int xenevtchn_fd(xenevtchn_handle *xce)
+{
+    return xce->fd;
+}
+
+int xenevtchn_notify(xenevtchn_handle *xce, evtchn_port_t port)
+{
+    int fd = xce->fd;
+    struct ioctl_evtchn_notify notify;
+
+    notify.port = port;
+
+    return ioctl(fd, IOCTL_EVTCHN_NOTIFY, &notify);
+}
+
+evtchn_port_or_error_t xenevtchn_bind_unbound_port(xenevtchn_handle *xce,
+                                                   int domid)
+{
+    int fd = xce->fd;
+    struct ioctl_evtchn_bind_unbound_port bind;
+
+    bind.remote_domain = domid;
+
+    return ioctl(fd, IOCTL_EVTCHN_BIND_UNBOUND_PORT, &bind);
+}
+
+evtchn_port_or_error_t xenevtchn_bind_interdomain(xenevtchn_handle *xce,
+                                                  int domid,
+                                                  evtchn_port_t remote_port)
+{
+    int fd = xce->fd;
+    struct ioctl_evtchn_bind_interdomain bind;
+
+    bind.remote_domain = domid;
+    bind.remote_port = remote_port;
+
+    return ioctl(fd, IOCTL_EVTCHN_BIND_INTERDOMAIN, &bind);
+}
+
+evtchn_port_or_error_t xenevtchn_bind_virq(xenevtchn_handle *xce,
+                                           unsigned int virq)
+{
+    int fd = xce->fd;
+    struct ioctl_evtchn_bind_virq bind;
+
+    bind.virq = virq;
+
+    return ioctl(fd, IOCTL_EVTCHN_BIND_VIRQ, &bind);
+}
+
+int xenevtchn_unbind(xenevtchn_handle *xce, evtchn_port_t port)
+{
+    int fd = xce->fd;
+    struct ioctl_evtchn_unbind unbind;
+
+    unbind.port = port;
+
+    return ioctl(fd, IOCTL_EVTCHN_UNBIND, &unbind);
+}
+
+evtchn_port_or_error_t xenevtchn_pending(xenevtchn_handle *xce)
+{
+    int fd = xce->fd;
+    evtchn_port_t port;
+
+    if ( read(fd, &port, sizeof(port)) != sizeof(port) )
+        return -1;
+
+    return port;
+}
+
+int xenevtchn_unmask(xenevtchn_handle *xce, evtchn_port_t port)
+{
+    int fd = xce->fd;
+
+    if ( write(fd, &port, sizeof(port)) != sizeof(port) )
+        return -1;
+    return 0;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxenevtchn/minios.c b/tools/libxenevtchn/minios.c
new file mode 100644
index 0000000..1408182
--- /dev/null
+++ b/tools/libxenevtchn/minios.c
@@ -0,0 +1,266 @@
+/******************************************************************************
+ *
+ * Copyright 2007-2008 Samuel Thibault <samuel.thibault@eu.citrix.com>.
+ * All rights reserved.
+ * Use is subject to license terms.
+ *
+ * This library 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 of the License.
+ *
+ * This library 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.
+ *
+ * Split off from xc_minios.c
+ */
+
+#include "xen-external/bsd-sys-queue.h"
+#include <mini-os/types.h>
+#include <mini-os/os.h>
+#include <mini-os/lib.h>
+#include <mini-os/events.h>
+#include <mini-os/wait.h>
+
+#include <sys/socket.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <malloc.h>
+
+#include "private.h"
+
+extern void minios_evtchn_close_fd(int fd);
+
+extern struct wait_queue_head event_queue;
+
+//void minios_evtchn_close_fd(int fd);
+
+/* XXX Note: This is not threadsafe */
+static struct evtchn_port_info* port_alloc(int fd) {
+    struct evtchn_port_info *port_info;
+    port_info = malloc(sizeof(struct evtchn_port_info));
+    if (port_info == NULL)
+        return NULL;
+    port_info->pending = 0;
+    port_info->port = -1;
+    port_info->bound = 0;
+
+    LIST_INSERT_HEAD(&files[fd].evtchn.ports, port_info, list);
+    return port_info;
+}
+
+static void port_dealloc(struct evtchn_port_info *port_info) {
+    if (port_info->bound)
+        unbind_evtchn(port_info->port);
+    LIST_REMOVE(port_info, list);
+    free(port_info);
+}
+
+int osdep_evtchn_open(xenevtchn_handle *xce)
+{
+    int fd = alloc_fd(FTYPE_EVTCHN);
+    if ( fd == -1 )
+        return -1;
+    LIST_INIT(&files[fd].evtchn.ports);
+    xce->fd = fd;
+    printf("evtchn_open() -> %d\n", fd);
+    return 0;
+}
+
+int osdep_evtchn_close(xenevtchn_handle *xce)
+{
+    if ( xce->fd == -1 )
+        return 0;
+
+    return close(xce->fd);
+}
+
+void minios_evtchn_close_fd(int fd)
+{
+    struct evtchn_port_info *port_info, *tmp;
+    LIST_FOREACH_SAFE(port_info, &files[fd].evtchn.ports, list, tmp)
+        port_dealloc(port_info);
+
+    files[fd].type = FTYPE_NONE;
+}
+
+int xenevtchn_fd(xenevtchn_handle *xce)
+{
+    return xce->fd;
+}
+
+int xenevtchn_notify(xenevtchn_handle *xce, evtchn_port_t port)
+{
+    int ret;
+
+    ret = notify_remote_via_evtchn(port);
+
+    if (ret < 0) {
+	errno = -ret;
+	ret = -1;
+    }
+    return ret;
+}
+
+static void evtchn_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
+{
+    int fd = (int)(intptr_t)data;
+    struct evtchn_port_info *port_info;
+    assert(files[fd].type == FTYPE_EVTCHN);
+    mask_evtchn(port);
+    LIST_FOREACH(port_info, &files[fd].evtchn.ports, list) {
+        if (port_info->port == port)
+            goto found;
+    }
+    printk("Unknown port for handle %d\n", fd);
+    return;
+
+ found:
+    port_info->pending = 1;
+    files[fd].read = 1;
+    wake_up(&event_queue);
+}
+
+evtchn_port_or_error_t xenevtchn_bind_unbound_port(xenevtchn_handle *xce, int domid)
+{
+    int fd = xce->fd;
+    struct evtchn_port_info *port_info;
+    int ret;
+    evtchn_port_t port;
+
+    assert(get_current() == main_thread);
+    port_info = port_alloc(fd);
+    if (port_info == NULL)
+	return -1;
+
+    printf("xenevtchn_bind_unbound_port(%d)", domid);
+    ret = evtchn_alloc_unbound(domid, evtchn_handler, (void*)(intptr_t)fd, &port);
+    printf(" = %d\n", ret);
+
+    if (ret < 0) {
+	port_dealloc(port_info);
+	errno = -ret;
+	return -1;
+    }
+    port_info->bound = 1;
+    port_info->port = port;
+    unmask_evtchn(port);
+    return port;
+}
+
+evtchn_port_or_error_t xenevtchn_bind_interdomain(xenevtchn_handle *xce, int domid,
+                                                  evtchn_port_t remote_port)
+{
+    int fd = xce->fd;
+    struct evtchn_port_info *port_info;
+    evtchn_port_t local_port;
+    int ret;
+
+    assert(get_current() == main_thread);
+    port_info = port_alloc(fd);
+    if (port_info == NULL)
+	return -1;
+
+    printf("xenevtchn_bind_interdomain(%d, %"PRId32")", domid, remote_port);
+    ret = evtchn_bind_interdomain(domid, remote_port, evtchn_handler, (void*)(intptr_t)fd, &local_port);
+    printf(" = %d\n", ret);
+
+    if (ret < 0) {
+	port_dealloc(port_info);
+	errno = -ret;
+	return -1;
+    }
+    port_info->bound = 1;
+    port_info->port = local_port;
+    unmask_evtchn(local_port);
+    return local_port;
+}
+
+int xenevtchn_unbind(xenevtchn_handle *xce, evtchn_port_t port)
+{
+    int fd = xce->fd;
+    struct evtchn_port_info *port_info;
+
+    LIST_FOREACH(port_info, &files[fd].evtchn.ports, list) {
+        if (port_info->port == port) {
+            port_dealloc(port_info);
+            return 0;
+        }
+    }
+    printf("Warning: couldn't find port %"PRId32" for xc handle %x\n", port, fd);
+    errno = EINVAL;
+    return -1;
+}
+
+evtchn_port_or_error_t xenevtchn_bind_virq(xenevtchn_handle *xce, unsigned int virq)
+{
+    int fd = xce->fd;
+    struct evtchn_port_info *port_info;
+    evtchn_port_t port;
+
+    assert(get_current() == main_thread);
+    port_info = port_alloc(fd);
+    if (port_info == NULL)
+	return -1;
+
+    printf("xenevtchn_bind_virq(%d)", virq);
+    port = bind_virq(virq, evtchn_handler, (void*)(intptr_t)fd);
+
+    if (port < 0) {
+	port_dealloc(port_info);
+	errno = -port;
+	return -1;
+    }
+    port_info->bound = 1;
+    port_info->port = port;
+    unmask_evtchn(port);
+    return port;
+}
+
+evtchn_port_or_error_t xenevtchn_pending(xenevtchn_handle *xce)
+{
+    int fd = xce->fd;
+    struct evtchn_port_info *port_info;
+    unsigned long flags;
+    evtchn_port_t ret = -1;
+
+    local_irq_save(flags);
+    files[fd].read = 0;
+
+    LIST_FOREACH(port_info, &files[fd].evtchn.ports, list) {
+        if (port_info->port != -1 && port_info->pending) {
+            if (ret == -1) {
+                ret = port_info->port;
+                port_info->pending = 0;
+            } else {
+                files[fd].read = 1;
+                break;
+            }
+        }
+    }
+    local_irq_restore(flags);
+    return ret;
+}
+
+int xenevtchn_unmask(xenevtchn_handle *xce, evtchn_port_t port)
+{
+    unmask_evtchn(port);
+    return 0;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxenevtchn/netbsd.c b/tools/libxenevtchn/netbsd.c
new file mode 100644
index 0000000..d9f0b71
--- /dev/null
+++ b/tools/libxenevtchn/netbsd.c
@@ -0,0 +1,144 @@
+/******************************************************************************
+ *
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * This library 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 of the License.
+ *
+ * This library 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.
+ *
+ * Split out from xc_netbsd.c
+ */
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <sys/ioctl.h>
+
+#include <xen/sys/evtchn.h>
+
+#include "private.h"
+
+#define EVTCHN_DEV_NAME  "/dev/xenevt"
+
+int osdep_evtchn_open(xenevtchn_handle *xce)
+{
+    int fd = open(EVTCHN_DEV_NAME, O_NONBLOCK|O_RDWR);
+    if ( fd == -1 )
+        return -1;
+    xce->fd = fd;
+    return 0;
+}
+
+int osdep_evtchn_close(xenevtchn_handle *xce)
+{
+    if ( xce->fd == -1 )
+        return 0;
+
+    return close(xce->fd);
+}
+
+int xenevtchn_fd(xenevtchn_handle *xce)
+{
+    return xce->fd;
+}
+
+int xenevtchn_notify(xenevtchn_handle *xce, evtchn_port_t port)
+{
+    int fd = xce->fd;
+    struct ioctl_evtchn_notify notify;
+
+    notify.port = port;
+
+    return ioctl(fd, IOCTL_EVTCHN_NOTIFY, &notify);
+}
+
+evtchn_port_or_error_t xenevtchn_bind_unbound_port(xenevtchn_handle * xce, int domid)
+{
+    int fd = xce->fd;
+    struct ioctl_evtchn_bind_unbound_port bind;
+    int ret;
+
+    bind.remote_domain = domid;
+
+    ret = ioctl(fd, IOCTL_EVTCHN_BIND_UNBOUND_PORT, &bind);
+    if (ret == 0)
+	return bind.port;
+    else
+	return -1;
+}
+
+evtchn_port_or_error_t xenevtchn_bind_interdomain(xenevtchn_handle *xce, int domid,
+                                                  evtchn_port_t remote_port)
+{
+    int fd = xce->fd;
+    struct ioctl_evtchn_bind_interdomain bind;
+    int ret;
+
+    bind.remote_domain = domid;
+    bind.remote_port = remote_port;
+
+    ret = ioctl(fd, IOCTL_EVTCHN_BIND_INTERDOMAIN, &bind);
+    if (ret == 0)
+	return bind.port;
+    else
+	return -1;
+}
+
+int xenevtchn_unbind(xenevtchn_handle *xce, evtchn_port_t port)
+{
+    int fd = xce->fd;
+    struct ioctl_evtchn_unbind unbind;
+
+    unbind.port = port;
+
+    return ioctl(fd, IOCTL_EVTCHN_UNBIND, &unbind);
+}
+
+evtchn_port_or_error_t xenevtchn_bind_virq(xenevtchn_handle *xce, unsigned int virq)
+{
+    int fd = xce->fd;
+    struct ioctl_evtchn_bind_virq bind;
+    int err;
+
+    bind.virq = virq;
+
+    err = ioctl(fd, IOCTL_EVTCHN_BIND_VIRQ, &bind);
+    if (err)
+	return -1;
+    else
+	return bind.port;
+}
+
+evtchn_port_or_error_t xenevtchn_pending(xenevtchn_handle *xce)
+{
+    int fd = xce->fd;
+    evtchn_port_t port;
+
+    if ( read_exact(fd, (char *)&port, sizeof(port)) == -1 )
+        return -1;
+
+    return port;
+}
+
+int xenevtchn_unmask(xenevtchn_handle *xce, evtchn_port_t port)
+{
+    int fd = xce->fd;
+    return write_exact(fd, (char *)&port, sizeof(port));
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxenevtchn/private.h b/tools/libxenevtchn/private.h
new file mode 100644
index 0000000..fcd0e96
--- /dev/null
+++ b/tools/libxenevtchn/private.h
@@ -0,0 +1,25 @@
+#ifndef XENEVTCHN_PRIVATE_H
+#define XENEVTCHN_PRIVATE_H
+
+#include <xentoollog.h>
+#include <xenevtchn.h>
+
+struct xenevtchn_handle {
+    xentoollog_logger *logger, *logger_tofree;
+    int fd;
+};
+
+int osdep_evtchn_open(xenevtchn_handle *xce);
+int osdep_evtchn_close(xenevtchn_handle *xce);
+
+#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxenevtchn/solaris.c b/tools/libxenevtchn/solaris.c
new file mode 100644
index 0000000..31df2d9
--- /dev/null
+++ b/tools/libxenevtchn/solaris.c
@@ -0,0 +1,132 @@
+/******************************************************************************
+ *
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * This library 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 of the License.
+ *
+ * This library 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.
+ *
+ * Split out from xc_solaris.c
+ */
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <sys/ioctl.h>
+
+#include <xen/sys/evtchn.h>
+
+#include "private.h"
+
+int osdep_evtchn_open(xenevtchn_handle *xce)
+{
+    int fd;
+
+    if ( (fd = open("/dev/xen/evtchn", O_RDWR)) == -1 )
+    {
+        PERROR("Could not open event channel interface");
+        return -1;
+    }
+
+    xce->fd = fd;
+    return 0;
+}
+
+int osdep_evtchn_close(xenevtchn_handle *xce)
+{
+    if ( xce->fd == -1 )
+        return 0;
+
+    return close(xce->fd);
+}
+
+int xenevtchn_fd(xenevtchn_handle *xce)
+{
+    return xce->fd;
+}
+
+int xenevtchn_notify(xenevtchn_handle *xce, evtchn_port_t port)
+{
+    int fd = xce->fd;
+    struct ioctl_evtchn_notify notify;
+
+    notify.port = port;
+
+    return ioctl(fd, IOCTL_EVTCHN_NOTIFY, &notify);
+}
+
+evtchn_port_or_error_t xenevtchn_bind_unbound_port(xenevtchn_handle *xce, int domid)
+{
+    int fd = xce->fd;
+    struct ioctl_evtchn_bind_unbound_port bind;
+
+    bind.remote_domain = domid;
+
+    return ioctl(fd, IOCTL_EVTCHN_BIND_UNBOUND_PORT, &bind);
+}
+
+evtchn_port_or_error_t xenevtchn_bind_interdomain(xenevtchn_handle *xce, int domid,
+                                                  evtchn_port_t remote_port)
+{
+    int fd = xce->fd;
+    struct ioctl_evtchn_bind_interdomain bind;
+
+    bind.remote_domain = domid;
+    bind.remote_port = remote_port;
+
+    return ioctl(fd, IOCTL_EVTCHN_BIND_INTERDOMAIN, &bind);
+}
+
+evtchn_port_or_error_t xenevtchn_bind_virq(xenevtchn_handle *xce, unsigned int virq)
+{
+    int fd = xce->fd;
+    struct ioctl_evtchn_bind_virq bind;
+
+    bind.virq = virq;
+
+    return ioctl(fd, IOCTL_EVTCHN_BIND_VIRQ, &bind);
+}
+
+int xenevtchn_unbind(xenevtchn_handle *xce, evtchn_port_t port)
+{
+    int fd = xce->fd;
+    struct ioctl_evtchn_unbind unbind;
+
+    unbind.port = port;
+
+    return ioctl(fd, IOCTL_EVTCHN_UNBIND, &unbind);
+}
+
+evtchn_port_or_error_t xenevtchn_pending(xenevtchn_handle *xce)
+{
+    int fd = xce->fd;
+    evtchn_port_t port;
+
+    if ( read_exact(fd, (char *)&port, sizeof(port)) == -1 )
+        return -1;
+
+    return port;
+}
+
+int xenevtchn_unmask(xenevtchn_handle *xce, evtchn_port_t port)
+{
+    int fd = xce->fd;
+    return write_exact(fd, (char *)&port, sizeof(port));
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxentoollog/include/xentoollog.h b/tools/libxentoollog/include/xentoollog.h
index 85d3da9..d08456c 100644
--- a/tools/libxentoollog/include/xentoollog.h
+++ b/tools/libxentoollog/include/xentoollog.h
@@ -135,3 +135,13 @@ const char *xtl_level_to_string(xentoollog_level); /* never fails */
 
 
 #endif /* XENTOOLLOG_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxentoollog/xtl_core.c b/tools/libxentoollog/xtl_core.c
index 73add92..ec2b155 100644
--- a/tools/libxentoollog/xtl_core.c
+++ b/tools/libxentoollog/xtl_core.c
@@ -82,3 +82,13 @@ void xtl_logger_destroy(struct xentoollog_logger *logger) {
     if (!logger) return;
     logger->destroy(logger);
 }
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxentoollog/xtl_logger_stdio.c b/tools/libxentoollog/xtl_logger_stdio.c
index b28ef73..1518176 100644
--- a/tools/libxentoollog/xtl_logger_stdio.c
+++ b/tools/libxentoollog/xtl_logger_stdio.c
@@ -191,3 +191,13 @@ xentoollog_logger_stdiostream *xtl_createlogger_stdiostream
 
     return XTL_NEW_LOGGER(stdiostream, newlogger);
 }
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxl/Makefile b/tools/libxl/Makefile
index cdf350a..ac57f66 100644
--- a/tools/libxl/Makefile
+++ b/tools/libxl/Makefile
@@ -20,12 +20,13 @@ LIBUUID_LIBS += -luuid
 endif
 
 LIBXL_LIBS =
-LIBXL_LIBS = $(LDLIBS_libxentoollog) $(LDLIBS_libxenctrl) $(LDLIBS_libxenguest) $(LDLIBS_libxenstore) $(LDLIBS_libblktapctl) $(PTYFUNCS_LIBS) $(LIBUUID_LIBS)
+LIBXL_LIBS = $(LDLIBS_libxentoollog) $(LDLIBS_libxenevtchn) $(LDLIBS_libxenctrl) $(LDLIBS_libxenguest) $(LDLIBS_libxenstore) $(LDLIBS_libblktapctl) $(PTYFUNCS_LIBS) $(LIBUUID_LIBS)
 ifeq ($(CONFIG_REMUS_NETBUF),y)
 LIBXL_LIBS += $(LIBNL3_LIBS)
 endif
 
 CFLAGS_LIBXL += $(CFLAGS_libxentoollog)
+CFLAGS_LIBXL += $(CFLAGS_libxenevtchn)
 CFLAGS_LIBXL += $(CFLAGS_libxenctrl)
 CFLAGS_LIBXL += $(CFLAGS_libxenguest)
 CFLAGS_LIBXL += $(CFLAGS_libxenstore)
@@ -158,7 +159,7 @@ $(XEN_INIT_DOM0_OBJS): CFLAGS += $(CFLAGS_libxenctrl)
 $(XEN_INIT_DOM0_OBJS): CFLAGS += $(CFLAGS_libxenstore)
 
 SAVE_HELPER_OBJS = libxl_save_helper.o _libxl_save_msgs_helper.o
-$(SAVE_HELPER_OBJS): CFLAGS += $(CFLAGS_libxenctrl)
+$(SAVE_HELPER_OBJS): CFLAGS += $(CFLAGS_libxenctrl) $(CFLAGS_libxenevtchn)
 
 PKG_CONFIG = xenlight.pc xlutil.pc
 
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 3fe1b99..5a5d344 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -186,7 +186,7 @@ int libxl_ctx_free(libxl_ctx *ctx)
     if (ctx->xch) xc_interface_close(ctx->xch);
     libxl_version_info_dispose(&ctx->version_info);
     if (ctx->xsh) xs_daemon_close(ctx->xsh);
-    if (ctx->xce) xc_evtchn_close(ctx->xce);
+    if (ctx->xce) xenevtchn_close(ctx->xce);
 
     libxl__poller_put(ctx, ctx->poller_app);
     ctx->poller_app = NULL;
diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c
index 81adb3d..dd830ac 100644
--- a/tools/libxl/libxl_dom.c
+++ b/tools/libxl/libxl_dom.c
@@ -1480,9 +1480,9 @@ static void domain_suspend_callback_common(libxl__egc *egc,
     if ((hvm_s_state == 0) && (dss->guest_evtchn.port >= 0)) {
         LOG(DEBUG, "issuing %s suspend request via event channel",
             dss->hvm ? "PVHVM" : "PV");
-        ret = xc_evtchn_notify(CTX->xce, dss->guest_evtchn.port);
+        ret = xenevtchn_notify(CTX->xce, dss->guest_evtchn.port);
         if (ret < 0) {
-            LOG(ERROR, "xc_evtchn_notify failed ret=%d", ret);
+            LOG(ERROR, "xenevtchn_notify failed ret=%d", ret);
             rc = ERROR_FAIL;
             goto err;
         }
diff --git a/tools/libxl/libxl_event.c b/tools/libxl/libxl_event.c
index 8acecfa..6dade69 100644
--- a/tools/libxl/libxl_event.c
+++ b/tools/libxl/libxl_event.c
@@ -744,7 +744,7 @@ static void evtchn_fd_callback(libxl__egc *egc, libxl__ev_fd *ev,
         /* OK, that's that workaround done.  We can actually check for
          * work for us to do: */
 
-        port = xc_evtchn_pending(CTX->xce);
+        port = xenevtchn_pending(CTX->xce);
         if (port < 0) {
             if (errno == EAGAIN)
                 break;
@@ -770,20 +770,20 @@ static void evtchn_fd_callback(libxl__egc *egc, libxl__ev_fd *ev,
 }
 
 int libxl__ctx_evtchn_init(libxl__gc *gc) {
-    xc_evtchn *xce;
+    xenevtchn_handle *xce;
     int rc, fd;
 
     if (CTX->xce)
         return 0;
 
-    xce = xc_evtchn_open(CTX->lg, 0);
+    xce = xenevtchn_open(CTX->lg, 0);
     if (!xce) {
         LOGE(ERROR,"cannot open libxc evtchn handle");
         rc = ERROR_FAIL;
         goto out;
     }
 
-    fd = xc_evtchn_fd(xce);
+    fd = xenevtchn_fd(xce);
     assert(fd >= 0);
 
     rc = libxl_fd_set_nonblock(CTX, fd, 1);
@@ -793,7 +793,7 @@ int libxl__ctx_evtchn_init(libxl__gc *gc) {
     return 0;
 
  out:
-    xc_evtchn_close(xce);
+    xenevtchn_close(xce);
     return rc;
 }
 
@@ -815,14 +815,14 @@ int libxl__ev_evtchn_wait(libxl__gc *gc, libxl__ev_evtchn *evev)
 
     if (!libxl__ev_fd_isregistered(&CTX->evtchn_efd)) {
         rc = libxl__ev_fd_register(gc, &CTX->evtchn_efd, evtchn_fd_callback,
-                                   xc_evtchn_fd(CTX->xce), POLLIN);
+                                   xenevtchn_fd(CTX->xce), POLLIN);
         if (rc) goto out;
     }
 
     if (evev->waiting)
         return 0;
 
-    r = xc_evtchn_unmask(CTX->xce, evev->port);
+    r = xenevtchn_unmask(CTX->xce, evev->port);
     if (r) {
         LOGE(ERROR,"cannot unmask event channel %d",evev->port);
         rc = ERROR_FAIL;
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 2b6b2a0..4b59cad 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -48,6 +48,7 @@
 #include <sys/file.h>
 #include <sys/ioctl.h>
 
+#include <xenevtchn.h>
 #include <xenstore.h>
 #include <xenctrl.h>
 #include <xenguest.h>
@@ -434,7 +435,7 @@ struct libxl__ctx {
     uint32_t watch_counter; /* helps disambiguate slot reuse */
     libxl__ev_fd watch_efd;
 
-    xc_evtchn *xce; /* waiting must be done only with libxl__ev_evtchn* */
+    xenevtchn_handle *xce; /* waiting must be done only with libxl__ev_evtchn* */
     LIBXL_LIST_HEAD(, libxl__ev_evtchn) evtchns_waiting;
     libxl__ev_fd evtchn_efd;
 
@@ -894,7 +895,7 @@ static inline int libxl__ev_xswatch_isregistered(const libxl__ev_xswatch *xw)
  * When the event is signaled then the callback will be made, once.
  * Then you must call libxl__ev_evtchn_wait again, if desired.
  *
- * You must NOT call xc_evtchn_unmask.  wait will do that for you.
+ * You must NOT call xenevtchn_unmask.  wait will do that for you.
  *
  * Calling libxl__ev_evtchn_cancel will arrange for libxl to disregard
  * future occurrences of event.  Both libxl__ev_evtchn_wait and
diff --git a/tools/misc/Makefile b/tools/misc/Makefile
index c4490f3..cf6a475 100644
--- a/tools/misc/Makefile
+++ b/tools/misc/Makefile
@@ -4,6 +4,7 @@ include $(XEN_ROOT)/tools/Rules.mk
 CFLAGS += -Werror
 # Include configure output (config.h)
 CFLAGS += -include $(XEN_ROOT)/tools/config.h
+CFLAGS += $(CFLAGS_libxenevtchn)
 CFLAGS += $(CFLAGS_libxenctrl)
 CFLAGS += $(CFLAGS_xeninclude)
 CFLAGS += $(CFLAGS_libxenstore)
@@ -88,18 +89,18 @@ xenlockprof: xenlockprof.o
 # xen-hptool incorrectly uses libxc internals
 xen-hptool.o: CFLAGS += -I$(XEN_ROOT)/tools/libxc
 xen-hptool: xen-hptool.o
-	$(CC) $(LDFLAGS) -o $@ $< $(LDLIBS_libxenctrl) $(LDLIBS_libxenguest) $(LDLIBS_libxenstore) $(APPEND_LDFLAGS)
+	$(CC) $(LDFLAGS) -o $@ $< $(LDLIBS_libxenevtchn) $(LDLIBS_libxenctrl) $(LDLIBS_libxenguest) $(LDLIBS_libxenstore) $(APPEND_LDFLAGS)
 
 # xen-mfndump incorrectly uses libxc internals
 xen-mfndump.o: CFLAGS += -I$(XEN_ROOT)/tools/libxc
 xen-mfndump: xen-mfndump.o
-	$(CC) $(LDFLAGS) -o $@ $< $(LDLIBS_libxenctrl) $(LDLIBS_libxenguest) $(APPEND_LDFLAGS)
+	$(CC) $(LDFLAGS) -o $@ $< $(LDLIBS_libxenevtchn) $(LDLIBS_libxenctrl) $(LDLIBS_libxenguest) $(APPEND_LDFLAGS)
 
 xenwatchdogd: xenwatchdogd.o
 	$(CC) $(LDFLAGS) -o $@ $< $(LDLIBS_libxenctrl) $(APPEND_LDFLAGS)
 
 xen-lowmemd: xen-lowmemd.o
-	$(CC) $(LDFLAGS) -o $@ $< $(LDLIBS_libxenctrl) $(LDLIBS_libxenstore) $(APPEND_LDFLAGS)
+	$(CC) $(LDFLAGS) -o $@ $< $(LDLIBS_libxenevtchn) $(LDLIBS_libxenctrl) $(LDLIBS_libxenstore) $(APPEND_LDFLAGS)
 
 gtraceview: gtraceview.o
 	$(CC) $(LDFLAGS) -o $@ $< $(CURSES_LIBS) $(TINFO_LIBS) $(APPEND_LDFLAGS)
diff --git a/tools/misc/xen-hptool.c b/tools/misc/xen-hptool.c
index c7561a9..ebcc9e8 100644
--- a/tools/misc/xen-hptool.c
+++ b/tools/misc/xen-hptool.c
@@ -1,3 +1,4 @@
+#include <xenevtchn.h>
 #include <xenctrl.h>
 #include <xc_private.h>
 #include <xc_core.h>
@@ -98,7 +99,7 @@ static int hp_mem_query_func(int argc, char *argv[])
     return ret;
 }
 
-static int suspend_guest(xc_interface *xch, xc_evtchn *xce, int domid,
+static int suspend_guest(xc_interface *xch, xenevtchn_handle *xce, int domid,
                          int *evtchn, int *lockfd)
 {
     int port, rc, suspend_evtchn = -1;
@@ -123,7 +124,7 @@ static int suspend_guest(xc_interface *xch, xc_evtchn *xce, int domid,
     }
     *evtchn = suspend_evtchn;
 
-    rc = xc_evtchn_notify(xce, suspend_evtchn);
+    rc = xenevtchn_notify(xce, suspend_evtchn);
     if (rc < 0)
     {
         fprintf(stderr, "Failed to notify suspend channel: errno %d\n", rc);
@@ -198,8 +199,8 @@ static int hp_mem_offline_func(int argc, char *argv[])
                 else if (status & PG_OFFLINE_OWNED)
                 {
                     int result, suspend_evtchn = -1, suspend_lockfd = -1;
-                    xc_evtchn *xce;
-                    xce = xc_evtchn_open(NULL, 0);
+                    xenevtchn_handle *xce;
+                    xce = xenevtchn_open(NULL, 0);
 
                     if (xce == NULL)
                     {
@@ -214,7 +215,7 @@ static int hp_mem_offline_func(int argc, char *argv[])
                     {
                         fprintf(stderr, "Failed to suspend guest %d for"
                                 " mfn %lx\n", domid, mfn);
-                        xc_evtchn_close(xce);
+                        xenevtchn_close(xce);
                         return -1;
                     }
 
@@ -238,7 +239,7 @@ static int hp_mem_offline_func(int argc, char *argv[])
                     xc_domain_resume(xch, domid, 1);
                     xc_suspend_evtchn_release(xch, xce, domid,
                                               suspend_evtchn, &suspend_lockfd);
-                    xc_evtchn_close(xce);
+                    xenevtchn_close(xce);
                 }
                 break;
             }
diff --git a/tools/misc/xen-lowmemd.c b/tools/misc/xen-lowmemd.c
index 82ffd75..3200404 100644
--- a/tools/misc/xen-lowmemd.c
+++ b/tools/misc/xen-lowmemd.c
@@ -4,22 +4,23 @@
  */
 
 #include <stdio.h>
+#include <xenevtchn.h>
 #include <xenctrl.h>
 #include <xenstore.h>
 #include <stdlib.h>
 #include <string.h>
 
 static evtchn_port_t virq_port      = -1;
-static xc_evtchn *xce_handle        = NULL;
+static xenevtchn_handle *xce_handle = NULL;
 static xc_interface *xch            = NULL;
 static struct xs_handle *xs_handle  = NULL;
 
 void cleanup(void)
 {
     if (virq_port > -1)
-        xc_evtchn_unbind(xce_handle, virq_port);
+        xenevtchn_unbind(xce_handle, virq_port);
     if (xce_handle)
-        xc_evtchn_close(xce_handle);
+        xenevtchn_close(xce_handle);
     if (xch)
         xc_interface_close(xch);
     if (xs_handle)
@@ -94,7 +95,7 @@ int main(int argc, char *argv[])
         return 1;
     }
 
-	xce_handle = xc_evtchn_open(NULL, 0);
+	xce_handle = xenevtchn_open(NULL, 0);
 	if (xce_handle == NULL)
     {
         perror("Failed to open evtchn device");
@@ -108,7 +109,7 @@ int main(int argc, char *argv[])
         return 3;
     }
 
-	if ((rc = xc_evtchn_bind_virq(xce_handle, VIRQ_ENOMEM)) == -1)
+	if ((rc = xenevtchn_bind_virq(xce_handle, VIRQ_ENOMEM)) == -1)
     {
         perror("Failed to bind to domain exception virq port");
         return 4;
@@ -120,7 +121,7 @@ int main(int argc, char *argv[])
     {
         evtchn_port_t port;
 
-        if ((port = xc_evtchn_pending(xce_handle)) == -1)
+        if ((port = xenevtchn_pending(xce_handle)) == -1)
         {
             perror("Failed to listen for pending event channel");
             return 5;
@@ -134,7 +135,7 @@ int main(int argc, char *argv[])
             return 6;
         }
 
-        if (xc_evtchn_unmask(xce_handle, port) == -1)
+        if (xenevtchn_unmask(xce_handle, port) == -1)
         {
             perror("Failed to unmask port");
             return 7;
diff --git a/tools/ocaml/libs/eventchn/Makefile b/tools/ocaml/libs/eventchn/Makefile
index 2d8d618..154efd4 100644
--- a/tools/ocaml/libs/eventchn/Makefile
+++ b/tools/ocaml/libs/eventchn/Makefile
@@ -2,13 +2,13 @@ TOPLEVEL=$(CURDIR)/../..
 XEN_ROOT=$(TOPLEVEL)/../..
 include $(TOPLEVEL)/common.make
 
-CFLAGS += $(CFLAGS_libxenctrl) $(CFLAGS_xeninclude)
+CFLAGS += $(CFLAGS_libxenevtchn) $(CFLAGS_xeninclude)
 
 OBJS = xeneventchn
 INTF = $(foreach obj, $(OBJS),$(obj).cmi)
 LIBS = xeneventchn.cma xeneventchn.cmxa
 
-LIBS_xeneventchn = $(LDLIBS_libxenctrl)
+LIBS_xeneventchn = $(LDLIBS_libxenevtchn)
 
 all: $(INTF) $(LIBS) $(PROGRAMS)
 
diff --git a/tools/ocaml/libs/eventchn/xeneventchn_stubs.c b/tools/ocaml/libs/eventchn/xeneventchn_stubs.c
index 5939e7c..c2d4737 100644
--- a/tools/ocaml/libs/eventchn/xeneventchn_stubs.c
+++ b/tools/ocaml/libs/eventchn/xeneventchn_stubs.c
@@ -24,7 +24,7 @@
 #include <xen/sysctl.h>
 #include <xen/xen.h>
 #include <xen/sys/evtchn.h>
-#include <xenctrl.h>
+#include <xenevtchn.h>
 
 #define CAML_NAME_SPACE
 #include <caml/mlvalues.h>
@@ -34,14 +34,14 @@
 #include <caml/callback.h>
 #include <caml/fail.h>
 
-#define _H(__h) ((xc_evtchn *)(__h))
+#define _H(__h) ((xenevtchn_handle *)(__h))
 
 CAMLprim value stub_eventchn_init(void)
 {
 	CAMLparam0();
 	CAMLlocal1(result);
 
-	xc_evtchn *xce = xc_evtchn_open(NULL, XC_OPENFLAG_NON_REENTRANT);
+	xenevtchn_handle *xce = xenevtchn_open(NULL, 0);
 	if (xce == NULL)
 		caml_failwith("open failed");
 
@@ -55,7 +55,7 @@ CAMLprim value stub_eventchn_fd(value xce)
 	CAMLlocal1(result);
 	int fd;
 
-	fd = xc_evtchn_fd(_H(xce));
+	fd = xenevtchn_fd(_H(xce));
 	if (fd == -1)
 		caml_failwith("evtchn fd failed");
 
@@ -69,7 +69,7 @@ CAMLprim value stub_eventchn_notify(value xce, value port)
 	CAMLparam2(xce, port);
 	int rc;
 
-	rc = xc_evtchn_notify(_H(xce), Int_val(port));
+	rc = xenevtchn_notify(_H(xce), Int_val(port));
 	if (rc == -1)
 		caml_failwith("evtchn notify failed");
 
@@ -83,7 +83,7 @@ CAMLprim value stub_eventchn_bind_interdomain(value xce, value domid,
 	CAMLlocal1(port);
 	evtchn_port_or_error_t rc;
 
-	rc = xc_evtchn_bind_interdomain(_H(xce), Int_val(domid), Int_val(remote_port));
+	rc = xenevtchn_bind_interdomain(_H(xce), Int_val(domid), Int_val(remote_port));
 	if (rc == -1)
 		caml_failwith("evtchn bind_interdomain failed");
 	port = Val_int(rc);
@@ -97,7 +97,7 @@ CAMLprim value stub_eventchn_bind_dom_exc_virq(value xce)
 	CAMLlocal1(port);
 	evtchn_port_or_error_t rc;
 
-	rc = xc_evtchn_bind_virq(_H(xce), VIRQ_DOM_EXC);
+	rc = xenevtchn_bind_virq(_H(xce), VIRQ_DOM_EXC);
 	if (rc == -1)
 		caml_failwith("evtchn bind_dom_exc_virq failed");
 	port = Val_int(rc);
@@ -110,7 +110,7 @@ CAMLprim value stub_eventchn_unbind(value xce, value port)
 	CAMLparam2(xce, port);
 	int rc;
 
-	rc = xc_evtchn_unbind(_H(xce), Int_val(port));
+	rc = xenevtchn_unbind(_H(xce), Int_val(port));
 	if (rc == -1)
 		caml_failwith("evtchn unbind failed");
 
@@ -123,7 +123,7 @@ CAMLprim value stub_eventchn_pending(value xce)
 	CAMLlocal1(result);
 	evtchn_port_or_error_t port;
 
-	port = xc_evtchn_pending(_H(xce));
+	port = xenevtchn_pending(_H(xce));
 	if (port == -1)
 		caml_failwith("evtchn pending failed");
 	result = Val_int(port);
@@ -137,7 +137,7 @@ CAMLprim value stub_eventchn_unmask(value xce, value _port)
 	evtchn_port_t port;
 
 	port = Int_val(_port);
-	if (xc_evtchn_unmask(_H(xce), port))
+	if (xenevtchn_unmask(_H(xce), port))
 		caml_failwith("evtchn unmask failed");
 	CAMLreturn(Val_unit);
 }
diff --git a/tools/python/setup.py b/tools/python/setup.py
index 5a03266..e6c8b18 100644
--- a/tools/python/setup.py
+++ b/tools/python/setup.py
@@ -8,13 +8,18 @@ extra_compile_args  = [ "-fno-strict-aliasing", "-Werror" ]
 
 PATH_XEN      = XEN_ROOT + "/tools/include"
 PATH_LIBXENTOOLLOG = XEN_ROOT + "/tools/libxentoollog"
+PATH_LIBXENEVTCHN = XEN_ROOT + "/tools/libxenevtchn"
 PATH_LIBXC    = XEN_ROOT + "/tools/libxc"
 PATH_LIBXL    = XEN_ROOT + "/tools/libxl"
 PATH_XENSTORE = XEN_ROOT + "/tools/xenstore"
 
 xc = Extension("xc",
                extra_compile_args = extra_compile_args,
-               include_dirs       = [ PATH_XEN, PATH_LIBXENTOOLLOG + "/include", PATH_LIBXC + "/include", "xen/lowlevel/xc" ],
+               include_dirs       = [ PATH_XEN,
+                                      PATH_LIBXENTOOLLOG + "/include",
+                                      PATH_LIBXENEVTCHN + "/include",
+                                      PATH_LIBXC + "/include",
+                                      "xen/lowlevel/xc" ],
                library_dirs       = [ PATH_LIBXC ],
                libraries          = [ "xenctrl", "xenguest" ],
                depends            = [ PATH_LIBXC + "/libxenctrl.so", PATH_LIBXC + "/libxenguest.so",  "-Wl,-rpath-link="+PATH_LIBXENTOOLLOG ],
diff --git a/tools/tests/xen-access/xen-access.c b/tools/tests/xen-access/xen-access.c
index e6ca9ba..545217e 100644
--- a/tools/tests/xen-access/xen-access.c
+++ b/tools/tests/xen-access/xen-access.c
@@ -79,7 +79,7 @@ static void close_handler(int sig)
 
 int xc_wait_for_event_or_timeout(xc_interface *xch, xc_evtchn *xce, unsigned long ms)
 {
-    struct pollfd fd = { .fd = xc_evtchn_fd(xce), .events = POLLIN | POLLERR };
+    struct pollfd fd = { .fd = xenevtchn_fd(xce), .events = POLLIN | POLLERR };
     int port;
     int rc;
 
diff --git a/tools/xcutils/Makefile b/tools/xcutils/Makefile
index fff519d..2d1f112 100644
--- a/tools/xcutils/Makefile
+++ b/tools/xcutils/Makefile
@@ -16,8 +16,8 @@ PROGRAMS = readnotes lsevtchn
 CFLAGS += -Werror
 
 # incorrectly uses libxc internals
-CFLAGS_readnotes.o  := $(CFLAGS_libxenctrl) $(CFLAGS_libxenguest) -I$(XEN_ROOT)/tools/libxc
-CFLAGS_lsevtchn.o   := $(CFLAGS_libxenctrl)
+CFLAGS_readnotes.o  := $(CFLAGS_libxenevtchn) $(CFLAGS_libxenctrl) $(CFLAGS_libxenguest) -I$(XEN_ROOT)/tools/libxc
+CFLAGS_lsevtchn.o   := $(CFLAGS_libxenevtchn) $(CFLAGS_libxenctrl)
 
 .PHONY: all
 all: build
diff --git a/tools/xenmon/Makefile b/tools/xenmon/Makefile
index 5095682..fa80983 100644
--- a/tools/xenmon/Makefile
+++ b/tools/xenmon/Makefile
@@ -14,8 +14,10 @@ XEN_ROOT=$(CURDIR)/../..
 include $(XEN_ROOT)/tools/Rules.mk
 
 CFLAGS  += -Werror
+CFLAGS  += $(CFLAGS_libxenevtchn)
 CFLAGS  += $(CFLAGS_libxenctrl)
 LDLIBS  += $(LDLIBS_libxenctrl)
+LDLIBS  += $(LDLIBS_libxenevtchn)
 
 SCRIPTS = xenmon.py
 
diff --git a/tools/xenmon/xenbaked.c b/tools/xenmon/xenbaked.c
index dc61d14..f092aec 100644
--- a/tools/xenmon/xenbaked.c
+++ b/tools/xenmon/xenbaked.c
@@ -38,6 +38,7 @@
 #include <unistd.h>
 #include <errno.h>
 #include <signal.h>
+#include <xenevtchn.h>
 #include <xenctrl.h>
 #include <xen/xen.h>
 #include <string.h>
@@ -268,7 +269,7 @@ static void log_event(int event_id)
 }
 
 int virq_port;
-xc_evtchn *xce_handle = NULL;
+xenevtchn_handle *xce_handle = NULL;
 
 /* Returns the event channel handle. */
 /* Stolen from xenstore code */
@@ -280,12 +281,12 @@ static int eventchn_init(void)
     if (0)
         return -1;
   
-    xce_handle = xc_evtchn_open(NULL, 0);
+    xce_handle = xenevtchn_open(NULL, 0);
 
     if (xce_handle == NULL)
         perror("Failed to open evtchn device");
   
-    if ((rc = xc_evtchn_bind_virq(xce_handle, VIRQ_TBUF)) == -1)
+    if ((rc = xenevtchn_bind_virq(xce_handle, VIRQ_TBUF)) == -1)
         perror("Failed to bind to domain exception virq port");
     virq_port = rc;
   
@@ -305,7 +306,7 @@ static void wait_for_event(void)
         return;
     }
 
-    evtchn_fd = xc_evtchn_fd(xce_handle);
+    evtchn_fd = xenevtchn_fd(xce_handle);
 
     FD_ZERO(&inset);
     FD_SET(evtchn_fd, &inset);
@@ -315,13 +316,13 @@ static void wait_for_event(void)
     ret = select(evtchn_fd+1, &inset, NULL, NULL, &tv);
   
     if ( (ret == 1) && FD_ISSET(evtchn_fd, &inset)) {
-        if ((port = xc_evtchn_pending(xce_handle)) == -1)
+        if ((port = xenevtchn_pending(xce_handle)) == -1)
             perror("Failed to read from event fd");
     
         //    if (port == virq_port)
         //      printf("got the event I was looking for\r\n");
 
-        if (xc_evtchn_unmask(xce_handle, port) == -1)
+        if (xenevtchn_unmask(xce_handle, port) == -1)
             perror("Failed to write to event fd");
     }
 }
diff --git a/tools/xenpaging/Makefile b/tools/xenpaging/Makefile
index e63d894..d491867 100644
--- a/tools/xenpaging/Makefile
+++ b/tools/xenpaging/Makefile
@@ -2,8 +2,8 @@ XEN_ROOT=$(CURDIR)/../..
 include $(XEN_ROOT)/tools/Rules.mk
 
 # xenpaging.c and file_ops.c incorrectly use libxc internals
-CFLAGS += $(CFLAGS_libxenctrl) $(CFLAGS_libxenstore) $(PTHREAD_CFLAGS) -I$(XEN_ROOT)/tools/libxc
-LDLIBS += $(LDLIBS_libxentoollog) $(LDLIBS_libxenctrl) $(LDLIBS_libxenstore) $(PTHREAD_LIBS)
+CFLAGS += $(CFLAGS_libxentoollog) $(CFLAGS_libxenevtchn) $(CFLAGS_libxenctrl) $(CFLAGS_libxenstore) $(PTHREAD_CFLAGS) -I$(XEN_ROOT)/tools/libxc
+LDLIBS += $(LDLIBS_libxentoollog) $(LDLIBS_libxenevtchn) $(LDLIBS_libxenctrl) $(LDLIBS_libxenstore) $(PTHREAD_LIBS)
 LDFLAGS += $(PTHREAD_LDFLAGS)
 
 POLICY    = default
diff --git a/tools/xenpaging/xenpaging.c b/tools/xenpaging/xenpaging.c
index 3f4c2e9..6776896 100644
--- a/tools/xenpaging/xenpaging.c
+++ b/tools/xenpaging/xenpaging.c
@@ -74,7 +74,7 @@ static void xenpaging_mem_paging_flush_ioemu_cache(struct xenpaging *paging)
 static int xenpaging_wait_for_event_or_timeout(struct xenpaging *paging)
 {
     xc_interface *xch = paging->xc_handle;
-    xc_evtchn *xce = paging->vm_event.xce_handle;
+    xenevtchn_handle *xce = paging->vm_event.xce_handle;
     char **vec, *val;
     unsigned int num;
     struct pollfd fd[2];
@@ -83,7 +83,7 @@ static int xenpaging_wait_for_event_or_timeout(struct xenpaging *paging)
     int timeout;
 
     /* Wait for event channel and xenstore */
-    fd[0].fd = xc_evtchn_fd(xce);
+    fd[0].fd = xenevtchn_fd(xce);
     fd[0].events = POLLIN | POLLERR;
     fd[1].fd = xs_fileno(paging->xs_handle);
     fd[1].events = POLLIN | POLLERR;
@@ -147,7 +147,7 @@ static int xenpaging_wait_for_event_or_timeout(struct xenpaging *paging)
     if ( rc && fd[0].revents & POLLIN )
     {
         DPRINTF("Got event from evtchn\n");
-        port = xc_evtchn_pending(xce);
+        port = xenevtchn_pending(xce);
         if ( port == -1 )
         {
             PERROR("Failed to read port from event channel");
@@ -155,7 +155,7 @@ static int xenpaging_wait_for_event_or_timeout(struct xenpaging *paging)
             goto err;
         }
 
-        rc = xc_evtchn_unmask(xce, port);
+        rc = xenevtchn_unmask(xce, port);
         if ( rc < 0 )
         {
             PERROR("Failed to unmask event channel port");
@@ -394,7 +394,7 @@ static struct xenpaging *xenpaging_init(int argc, char *argv[])
     }
 
     /* Open event channel */
-    paging->vm_event.xce_handle = xc_evtchn_open(NULL, 0);
+    paging->vm_event.xce_handle = xenevtchn_open(NULL, 0);
     if ( paging->vm_event.xce_handle == NULL )
     {
         PERROR("Failed to open event channel");
@@ -402,7 +402,7 @@ static struct xenpaging *xenpaging_init(int argc, char *argv[])
     }
 
     /* Bind event notification */
-    rc = xc_evtchn_bind_interdomain(paging->vm_event.xce_handle,
+    rc = xenevtchn_bind_interdomain(paging->vm_event.xce_handle,
                                     paging->vm_event.domain_id,
                                     paging->vm_event.evtchn_port);
     if ( rc < 0 )
@@ -532,7 +532,7 @@ static void xenpaging_teardown(struct xenpaging *paging)
     }
 
     /* Unbind VIRQ */
-    rc = xc_evtchn_unbind(paging->vm_event.xce_handle, paging->vm_event.port);
+    rc = xenevtchn_unbind(paging->vm_event.xce_handle, paging->vm_event.port);
     if ( rc != 0 )
     {
         PERROR("Error unbinding event port");
@@ -540,7 +540,7 @@ static void xenpaging_teardown(struct xenpaging *paging)
     paging->vm_event.port = -1;
 
     /* Close event channel */
-    rc = xc_evtchn_close(paging->vm_event.xce_handle);
+    rc = xenevtchn_close(paging->vm_event.xce_handle);
     if ( rc != 0 )
     {
         PERROR("Error closing event channel");
@@ -693,7 +693,7 @@ static int xenpaging_resume_page(struct xenpaging *paging, vm_event_response_t *
     }
 
     /* Tell Xen page is ready */
-    return xc_evtchn_notify(paging->vm_event.xce_handle, paging->vm_event.port);
+    return xenevtchn_notify(paging->vm_event.xce_handle, paging->vm_event.port);
 }
 
 static int xenpaging_populate_page(struct xenpaging *paging, unsigned long gfn, int i)
diff --git a/tools/xenpaging/xenpaging.h b/tools/xenpaging/xenpaging.h
index 25d511d..6c12030 100644
--- a/tools/xenpaging/xenpaging.h
+++ b/tools/xenpaging/xenpaging.h
@@ -25,6 +25,7 @@
 #define __XEN_PAGING2_H__
 
 
+#include <xenevtchn.h>
 #include <xc_private.h>
 #include <xen/event_channel.h>
 #include <xen/vm_event.h>
@@ -33,7 +34,7 @@
 
 struct vm_event {
     domid_t domain_id;
-    xc_evtchn *xce_handle;
+    xenevtchn_handle *xce_handle;
     int port;
     vm_event_back_ring_t back_ring;
     uint32_t evtchn_port;
diff --git a/tools/xenstore/Makefile b/tools/xenstore/Makefile
index 1b4a494..c161046 100644
--- a/tools/xenstore/Makefile
+++ b/tools/xenstore/Makefile
@@ -9,6 +9,7 @@ CFLAGS += -I.
 # Include configure output (config.h)
 CFLAGS += -include $(XEN_ROOT)/tools/config.h
 CFLAGS += -I./include
+CFLAGS += $(CFLAGS_libxenevtchn)
 CFLAGS += $(CFLAGS_libxenctrl)
 CFLAGS += -DXEN_LIB_STORED="\"$(XEN_LIB_STORED)\""
 
@@ -75,10 +76,10 @@ endif
 init-xenstore-domain.o: CFLAGS += $(CFLAGS_libxenguest)
 
 init-xenstore-domain: init-xenstore-domain.o $(LIBXENSTORE)
-	$(CC) $^ $(LDFLAGS) $(LDLIBS_libxenctrl) $(LDLIBS_libxenguest) $(LDLIBS_libxenstore) -o $@ $(APPEND_LDFLAGS)
+	$(CC) $^ $(LDFLAGS) $(LDLIBS_libxenevtchn) $(LDLIBS_libxenctrl) $(LDLIBS_libxenguest) $(LDLIBS_libxenstore) -o $@ $(APPEND_LDFLAGS)
 
 xenstored: $(XENSTORED_OBJS)
-	$(CC) $^ $(LDFLAGS) $(LDLIBS_libxenctrl) $(SOCKET_LIBS) -o $@ $(APPEND_LDFLAGS)
+	$(CC) $^ $(LDFLAGS) $(LDLIBS_libxenevtchn) $(LDLIBS_libxenctrl) $(SOCKET_LIBS) -o $@ $(APPEND_LDFLAGS)
 
 xenstored.a: $(XENSTORED_OBJS)
 	$(AR) cr $@ $^
diff --git a/tools/xenstore/xenstored_core.c b/tools/xenstore/xenstored_core.c
index b18000d..7f1e489 100644
--- a/tools/xenstore/xenstored_core.c
+++ b/tools/xenstore/xenstored_core.c
@@ -41,6 +41,8 @@
 #include <assert.h>
 #include <setjmp.h>
 
+#include <xenevtchn.h>
+
 #include "utils.h"
 #include "list.h"
 #include "talloc.h"
@@ -64,7 +66,7 @@
 #include <systemd/sd-daemon.h>
 #endif
 
-extern xc_evtchn *xce_handle; /* in xenstored_domain.c */
+extern xenevtchn_handle *xce_handle; /* in xenstored_domain.c */
 static int xce_pollfd_idx = -1;
 static struct pollfd *fds;
 static unsigned int current_array_size;
@@ -373,7 +375,7 @@ static void initialize_fds(int sock, int *p_sock_pollfd_idx,
 			set_fd(reopen_log_pipe[0], POLLIN|POLLPRI);
 
 	if (xce_handle != NULL)
-		xce_pollfd_idx = set_fd(xc_evtchn_fd(xce_handle),
+		xce_pollfd_idx = set_fd(xenevtchn_fd(xce_handle),
 					POLLIN|POLLPRI);
 
 	list_for_each_entry(conn, &connections, list) {
diff --git a/tools/xenstore/xenstored_domain.c b/tools/xenstore/xenstored_domain.c
index 0776e39..b649107 100644
--- a/tools/xenstore/xenstored_domain.c
+++ b/tools/xenstore/xenstored_domain.c
@@ -30,6 +30,7 @@
 #include "xenstored_transaction.h"
 #include "xenstored_watch.h"
 
+#include <xenevtchn.h>
 #include <xenctrl.h>
 #include <xen/grant_table.h>
 
@@ -37,7 +38,7 @@ static xc_interface **xc_handle;
 xc_gnttab **xcg_handle;
 static evtchn_port_t virq_port;
 
-xc_evtchn *xce_handle = NULL;
+xenevtchn_handle *xce_handle = NULL;
 
 struct domain
 {
@@ -129,7 +130,7 @@ static int writechn(struct connection *conn,
 	xen_mb();
 	intf->rsp_prod += len;
 
-	xc_evtchn_notify(xce_handle, conn->domain->port);
+	xenevtchn_notify(xce_handle, conn->domain->port);
 
 	return len;
 }
@@ -159,7 +160,7 @@ static int readchn(struct connection *conn, void *data, unsigned int len)
 	xen_mb();
 	intf->req_cons += len;
 
-	xc_evtchn_notify(xce_handle, conn->domain->port);
+	xenevtchn_notify(xce_handle, conn->domain->port);
 
 	return len;
 }
@@ -191,7 +192,7 @@ static int destroy_domain(void *_domain)
 	list_del(&domain->list);
 
 	if (domain->port) {
-		if (xc_evtchn_unbind(xce_handle, domain->port) == -1)
+		if (xenevtchn_unbind(xce_handle, domain->port) == -1)
 			eprintf("> Unbinding port %i failed!\n", domain->port);
 	}
 
@@ -240,13 +241,13 @@ void handle_event(void)
 {
 	evtchn_port_t port;
 
-	if ((port = xc_evtchn_pending(xce_handle)) == -1)
+	if ((port = xenevtchn_pending(xce_handle)) == -1)
 		barf_perror("Failed to read from event fd");
 
 	if (port == virq_port)
 		domain_cleanup();
 
-	if (xc_evtchn_unmask(xce_handle, port) == -1)
+	if (xenevtchn_unmask(xce_handle, port) == -1)
 		barf_perror("Failed to write to event fd");
 }
 
@@ -288,7 +289,7 @@ static struct domain *new_domain(void *context, unsigned int domid,
 	talloc_set_destructor(domain, destroy_domain);
 
 	/* Tell kernel we're interested in this event. */
-	rc = xc_evtchn_bind_interdomain(xce_handle, domid, port);
+	rc = xenevtchn_bind_interdomain(xce_handle, domid, port);
 	if (rc == -1)
 	    return NULL;
 	domain->port = rc;
@@ -393,8 +394,8 @@ void do_introduce(struct connection *conn, struct buffered_data *in)
 	} else if ((domain->mfn == mfn) && (domain->conn != conn)) {
 		/* Use XS_INTRODUCE for recreating the xenbus event-channel. */
 		if (domain->port)
-			xc_evtchn_unbind(xce_handle, domain->port);
-		rc = xc_evtchn_bind_interdomain(xce_handle, domid, port);
+			xenevtchn_unbind(xce_handle, domain->port);
+		rc = xenevtchn_bind_interdomain(xce_handle, domid, port);
 		domain->port = (rc == -1) ? 0 : rc;
 		domain->remote_port = port;
 	} else {
@@ -615,7 +616,7 @@ static int dom0_init(void)
 
 	talloc_steal(dom0->conn, dom0); 
 
-	xc_evtchn_notify(xce_handle, dom0->port); 
+	xenevtchn_notify(xce_handle, dom0->port); 
 
 	return 0; 
 }
@@ -644,7 +645,7 @@ void domain_init(void)
 	else
 		talloc_set_destructor(xcg_handle, close_xcg_handle);
 
-	xce_handle = xc_evtchn_open(NULL, 0);
+	xce_handle = xenevtchn_open(NULL, 0);
 
 	if (xce_handle == NULL)
 		barf_perror("Failed to open evtchn device");
@@ -652,7 +653,7 @@ void domain_init(void)
 	if (dom0_init() != 0) 
 		barf_perror("Failed to initialize dom0 state"); 
 
-	if ((rc = xc_evtchn_bind_virq(xce_handle, VIRQ_DOM_EXC)) == -1)
+	if ((rc = xenevtchn_bind_virq(xce_handle, VIRQ_DOM_EXC)) == -1)
 		barf_perror("Failed to bind to domain exception virq port");
 	virq_port = rc;
 }
diff --git a/tools/xentrace/Makefile b/tools/xentrace/Makefile
index 2f57bda..ab27284 100644
--- a/tools/xentrace/Makefile
+++ b/tools/xentrace/Makefile
@@ -3,8 +3,11 @@ include $(XEN_ROOT)/tools/Rules.mk
 
 CFLAGS += -Werror
 
+CFLAGS += $(CFLAGS_libxenevtchn)
 CFLAGS += $(CFLAGS_libxenctrl)
-LDLIBS += $(LDLIBS_libxenctrl) $(ARGP_LDFLAGS)
+LDLIBS += $(LDLIBS_libxenevtchn)
+LDLIBS += $(LDLIBS_libxenctrl)
+LDLIBS += $(ARGP_LDFLAGS)
 
 BIN-$(CONFIG_X86) = xenalyze
 BIN      = $(BIN-y)
diff --git a/tools/xentrace/xentrace.c b/tools/xentrace/xentrace.c
index 4ee1458..c970d42 100644
--- a/tools/xentrace/xentrace.c
+++ b/tools/xentrace/xentrace.c
@@ -30,6 +30,7 @@
 #include <xen/xen.h>
 #include <xen/trace.h>
 
+#include <xenevtchn.h>
 #include <xenctrl.h>
 
 #define PERROR(_m, _a...)                                       \
@@ -74,7 +75,7 @@ settings_t opts;
 int interrupted = 0; /* gets set if we get a SIGHUP */
 
 static xc_interface *xc_handle;
-static xc_evtchn *xce_handle = NULL;
+static xenevtchn_handle *xce_handle = NULL;
 static int virq_port = -1;
 static int outfd = 1;
 
@@ -602,13 +603,13 @@ static void event_init(void)
 {
     int rc;
 
-    xce_handle = xc_evtchn_open(NULL, 0);
+    xce_handle = xenevtchn_open(NULL, 0);
     if (xce_handle == NULL) {
         perror("event channel open");
         exit(EXIT_FAILURE);
     }
 
-    rc = xc_evtchn_bind_virq(xce_handle, VIRQ_TBUF);
+    rc = xenevtchn_bind_virq(xce_handle, VIRQ_TBUF);
     if (rc == -1) {
         PERROR("failed to bind to VIRQ port");
         exit(EXIT_FAILURE);
@@ -623,7 +624,7 @@ static void event_init(void)
 static void wait_for_event_or_timeout(unsigned long milliseconds)
 {
     int rc;
-    struct pollfd fd = { .fd = xc_evtchn_fd(xce_handle),
+    struct pollfd fd = { .fd = xenevtchn_fd(xce_handle),
                          .events = POLLIN | POLLERR };
     int port;
 
@@ -636,7 +637,7 @@ static void wait_for_event_or_timeout(unsigned long milliseconds)
     }
 
     if (rc == 1) {
-        port = xc_evtchn_pending(xce_handle);
+        port = xenevtchn_pending(xce_handle);
         if (port == -1) {
             PERROR("failed to read port from evtchn");
             exit(EXIT_FAILURE);
@@ -647,7 +648,7 @@ static void wait_for_event_or_timeout(unsigned long milliseconds)
                     port, virq_port);
             exit(EXIT_FAILURE);
         }
-        rc = xc_evtchn_unmask(xce_handle, port);
+        rc = xenevtchn_unmask(xce_handle, port);
         if (rc == -1) {
             PERROR("failed to write port to evtchn");
             exit(EXIT_FAILURE);
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH XEN v2 06/15] tools: Arrange to check public headers for ANSI compatiblity
  2015-07-15 15:46 [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries Ian Campbell
                   ` (4 preceding siblings ...)
  2015-07-15 15:46 ` [PATCH XEN v2 05/15] tools: Refactor /dev/xen/evtchn wrappers into libxenevtchn Ian Campbell
@ 2015-07-15 15:46 ` Ian Campbell
  2015-07-15 15:46 ` [PATCH XEN v2 07/15] tools/libxc: Remove osdep indirection for xc_gnt{shr, tab} Ian Campbell
                   ` (21 subsequent siblings)
  27 siblings, 0 replies; 55+ messages in thread
From: Ian Campbell @ 2015-07-15 15:46 UTC (permalink / raw)
  To: ian.jackson, wei.liu2, xen-devel
  Cc: roger.pau, Ian Campbell, stefano.stabellini

Using the same rune as we use for the Xen public headers, except we do
not need stdint.h here and we use -pedantic too.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
---
 .gitignore                   | 2 ++
 tools/Rules.mk               | 8 ++++++++
 tools/libxenevtchn/Makefile  | 4 +++-
 tools/libxentoollog/Makefile | 5 ++++-
 4 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/.gitignore b/.gitignore
index ed6bac6..61167d9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -87,6 +87,8 @@ tools/config.cache
 config/Tools.mk
 config/Stubdom.mk
 config/Docs.mk
+tools/libxentoollog/headers.chk
+tools/libxenevtchn/headers.chk
 tools/blktap2/daemon/blktapctrl
 tools/blktap2/drivers/img2qcow
 tools/blktap2/drivers/lock-util
diff --git a/tools/Rules.mk b/tools/Rules.mk
index e200eb7..f675fa7 100644
--- a/tools/Rules.mk
+++ b/tools/Rules.mk
@@ -176,6 +176,14 @@ INSTALL_PYTHON_PROG = \
 %.opic: %.S
 	$(CC) $(CPPFLAGS) -DPIC $(CFLAGS) $(CFLAGS.opic) -fPIC -c -o $@ $< $(APPEND_CFLAGS)
 
+headers.chk:
+	for i in $(filter %.h,$^); do \
+	    $(CC) -x c -ansi -Wall -Werror -pedantic $(CFLAGS_xeninclude) \
+	          -S -o /dev/null $$i || exit 1; \
+	    echo $$i; \
+	done >$@.new
+	mv $@.new $@
+
 subdirs-all subdirs-clean subdirs-install subdirs-distclean: .phony
 	@set -e; for subdir in $(SUBDIRS) $(SUBDIRS-y); do \
 		$(MAKE) subdir-$(patsubst subdirs-%,%,$@)-$$subdir; \
diff --git a/tools/libxenevtchn/Makefile b/tools/libxenevtchn/Makefile
index c3ea3c2..f180cee5 100644
--- a/tools/libxenevtchn/Makefile
+++ b/tools/libxenevtchn/Makefile
@@ -32,8 +32,9 @@ build:
 	$(MAKE) libs
 
 .PHONY: libs
-libs: $(LIB)
+libs: headers.chk $(LIB)
 
+headers.chk: $(wildcard include/*.h)
 
 libxenevtchn.a: $(LIB_OBJS)
 	$(AR) rc $@ $^
@@ -63,3 +64,4 @@ TAGS:
 .PHONY: clean
 clean:
 	rm -rf *.rpm $(LIB) *~ $(DEPS) $(LIB_OBJS) $(PIC_OBJS)
+	rm -f headers.chk
diff --git a/tools/libxentoollog/Makefile b/tools/libxentoollog/Makefile
index 0c8be13..f8153ec 100644
--- a/tools/libxentoollog/Makefile
+++ b/tools/libxentoollog/Makefile
@@ -27,7 +27,9 @@ build:
 	$(MAKE) libs
 
 .PHONY: libs
-libs: $(LIB)
+libs: headers.chk $(LIB)
+
+headers.chk: $(wildcard include/*.h)
 
 libxentoollog.a: $(LIB_OBJS)
 	$(AR) rc $@ $^
@@ -57,3 +59,4 @@ TAGS:
 .PHONY: clean
 clean:
 	rm -rf *.rpm $(LIB) *~ $(DEPS) $(LIB_OBJS) $(PIC_OBJS)
+	rm -f headers.chk
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH XEN v2 07/15] tools/libxc: Remove osdep indirection for xc_gnt{shr, tab}
  2015-07-15 15:46 [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries Ian Campbell
                   ` (5 preceding siblings ...)
  2015-07-15 15:46 ` [PATCH XEN v2 06/15] tools: Arrange to check public headers for ANSI compatiblity Ian Campbell
@ 2015-07-15 15:46 ` Ian Campbell
  2015-07-15 15:46 ` [PATCH XEN v2 08/15] tools: Refactor /dev/xen/gnt{dev, shr} wrappers into libxengnttab Ian Campbell
                   ` (20 subsequent siblings)
  27 siblings, 0 replies; 55+ messages in thread
From: Ian Campbell @ 2015-07-15 15:46 UTC (permalink / raw)
  To: ian.jackson, wei.liu2, xen-devel
  Cc: roger.pau, Ian Campbell, stefano.stabellini

The alternative backend (a xen-api/xapi shim) is no longer around and
so this stuff is now just baggage which is getting in the way of
refactoring libxenctrl.

Nested virt probably suffices for this use case now.

It is now necessary to provide explicit versions of things for
platforms which do not implement this functionality, since the osdep
dispatcher cannot fulfil this need any more. These are provided by
appropriate xc_nognt???.c files which are compiled and linked on the
appropriate platforms. In them open and close return failure and
everything else aborts, since if open fails they should never be
called.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
---
 tools/libxc/Makefile               |  10 ++--
 tools/libxc/include/xenctrl.h      |   4 +-
 tools/libxc/include/xenctrlosdep.h |  23 -------
 tools/libxc/xc_gnttab.c            |  57 ++++--------------
 tools/libxc/xc_linux_osdep.c       | 119 +++++++++++++++----------------------
 tools/libxc/xc_minios.c            |  51 ++++++----------
 tools/libxc/xc_nogntshr.c          |  44 ++++++++++++++
 tools/libxc/xc_nognttab.c          |  48 +++++++++++++++
 tools/libxc/xc_private.c           |  83 +++++++++++++++++++++-----
 tools/libxc/xc_private.h           |  24 ++++++++
 10 files changed, 270 insertions(+), 193 deletions(-)
 create mode 100644 tools/libxc/xc_nogntshr.c
 create mode 100644 tools/libxc/xc_nognttab.c

diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile
index baf054f..19ad0df 100644
--- a/tools/libxc/Makefile
+++ b/tools/libxc/Makefile
@@ -42,11 +42,11 @@ CTRL_SRCS-y       += xc_resource.c
 CTRL_SRCS-$(CONFIG_X86) += xc_psr.c
 CTRL_SRCS-$(CONFIG_X86) += xc_pagetab.c
 CTRL_SRCS-$(CONFIG_Linux) += xc_linux.c xc_linux_osdep.c
-CTRL_SRCS-$(CONFIG_FreeBSD) += xc_freebsd.c xc_freebsd_osdep.c
-CTRL_SRCS-$(CONFIG_SunOS) += xc_solaris.c
-CTRL_SRCS-$(CONFIG_NetBSD) += xc_netbsd.c
-CTRL_SRCS-$(CONFIG_NetBSDRump) += xc_netbsd.c
-CTRL_SRCS-$(CONFIG_MiniOS) += xc_minios.c
+CTRL_SRCS-$(CONFIG_FreeBSD) += xc_freebsd.c xc_freebsd_osdep.c xc_nognttab.c xc_nogntshr.c
+CTRL_SRCS-$(CONFIG_SunOS) += xc_solaris.c xc_nognttab.c xc_nogntshr.c
+CTRL_SRCS-$(CONFIG_NetBSD) += xc_netbsd.c xc_nognttab.c xc_nogntshr.c
+CTRL_SRCS-$(CONFIG_NetBSDRump) += xc_netbsd.c xc_nognttab.c xc_nogntshr.c
+CTRL_SRCS-$(CONFIG_MiniOS) += xc_minios.c xc_nogntshr.c
 CTRL_SRCS-y       += xc_evtchn_compat.c
 
 GUEST_SRCS-y :=
diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h
index d7ca161..e60aa34 100644
--- a/tools/libxc/include/xenctrl.h
+++ b/tools/libxc/include/xenctrl.h
@@ -118,8 +118,8 @@
  */
 
 typedef struct xc_interface_core xc_interface;
-typedef struct xc_interface_core xc_gnttab;
-typedef struct xc_interface_core xc_gntshr;
+typedef struct xengntdev_handle xc_gnttab;
+typedef struct xengntdev_handle xc_gntshr;
 
 enum xc_error_code {
   XC_ERROR_NONE = 0,
diff --git a/tools/libxc/include/xenctrlosdep.h b/tools/libxc/include/xenctrlosdep.h
index a8b27ae..bad10f6 100644
--- a/tools/libxc/include/xenctrlosdep.h
+++ b/tools/libxc/include/xenctrlosdep.h
@@ -52,8 +52,6 @@
 
 enum xc_osdep_type {
     XC_OSDEP_PRIVCMD,
-    XC_OSDEP_GNTTAB,
-    XC_OSDEP_GNTSHR,
 };
 
 /* Opaque handle internal to the backend */
@@ -89,27 +87,6 @@ struct xc_osdep_ops
                                         size_t chunksize, privcmd_mmap_entry_t entries[],
                                         int nentries);
         } privcmd;
-        struct {
-#define XC_GRANT_MAP_SINGLE_DOMAIN 0x1
-            void *(*grant_map)(xc_gnttab *xcg, xc_osdep_handle h,
-                               uint32_t count, int flags, int prot,
-                               uint32_t *domids, uint32_t *refs,
-                               uint32_t notify_offset,
-                               evtchn_port_t notify_port);
-            int (*munmap)(xc_gnttab *xcg, xc_osdep_handle h,
-                          void *start_address,
-                          uint32_t count);
-            int (*set_max_grants)(xc_gnttab *xcg, xc_osdep_handle h, uint32_t count);
-        } gnttab;
-        struct {
-            void *(*share_pages)(xc_gntshr *xcg, xc_osdep_handle h,
-                                 uint32_t domid, int count,
-                                 uint32_t *refs, int writable,
-                                 uint32_t notify_offset,
-                                 evtchn_port_t notify_port);
-            int (*munmap)(xc_gntshr *xcg, xc_osdep_handle h,
-                          void *start_address, uint32_t count);
-        } gntshr;
     } u;
 };
 typedef struct xc_osdep_ops xc_osdep_ops;
diff --git a/tools/libxc/xc_gnttab.c b/tools/libxc/xc_gnttab.c
index 4076e47..53cd670 100644
--- a/tools/libxc/xc_gnttab.c
+++ b/tools/libxc/xc_gnttab.c
@@ -144,68 +144,48 @@ grant_entry_v2_t *xc_gnttab_map_table_v2(xc_interface *xch, int domid,
     return _gnttab_map_table(xch, domid, gnt_num);
 }
 
-void *xc_gnttab_map_grant_ref(xc_gnttab *xcg,
+void *xc_gnttab_map_grant_ref(xc_gnttab *xgt,
                               uint32_t domid,
                               uint32_t ref,
                               int prot)
 {
-	return xcg->ops->u.gnttab.grant_map(xcg, xcg->ops_handle, 1, 0, prot,
-	                                    &domid, &ref, -1, -1);
+    return osdep_gnttab_grant_map(xgt, 1, 0, prot, &domid, &ref, -1, -1);
 }
 
-void *xc_gnttab_map_grant_refs(xc_gnttab *xcg,
+void *xc_gnttab_map_grant_refs(xc_gnttab *xgt,
                                uint32_t count,
                                uint32_t *domids,
                                uint32_t *refs,
                                int prot)
 {
-	return xcg->ops->u.gnttab.grant_map(xcg, xcg->ops_handle, count, 0,
-	                                    prot, domids, refs, -1, -1);
+    return osdep_gnttab_grant_map(xgt, count, 0, prot, domids, refs, -1, -1);
 }
 
-void *xc_gnttab_map_domain_grant_refs(xc_gnttab *xcg,
+void *xc_gnttab_map_domain_grant_refs(xc_gnttab *xgt,
                                       uint32_t count,
                                       uint32_t domid,
                                       uint32_t *refs,
                                       int prot)
 {
-	return xcg->ops->u.gnttab.grant_map(xcg, xcg->ops_handle, count,
-	                                    XC_GRANT_MAP_SINGLE_DOMAIN,
-	                                    prot, &domid, refs, -1, -1);
+    return osdep_gnttab_grant_map(xgt, count, XC_GRANT_MAP_SINGLE_DOMAIN,
+                                  prot, &domid, refs, -1, -1);
 }
 
-void *xc_gnttab_map_grant_ref_notify(xc_gnttab *xcg,
+void *xc_gnttab_map_grant_ref_notify(xc_gnttab *xgt,
                                      uint32_t domid,
                                      uint32_t ref,
                                      int prot,
                                      uint32_t notify_offset,
                                      evtchn_port_t notify_port)
 {
-	return xcg->ops->u.gnttab.grant_map(xcg, xcg->ops_handle, 1, 0, prot,
-	                              &domid, &ref, notify_offset, notify_port);
-}
-
-
-int xc_gnttab_munmap(xc_gnttab *xcg,
-                     void *start_address,
-                     uint32_t count)
-{
-	return xcg->ops->u.gnttab.munmap(xcg, xcg->ops_handle,
-					 start_address, count);
-}
-
-int xc_gnttab_set_max_grants(xc_gnttab *xcg, uint32_t count)
-{
-	if (!xcg->ops->u.gnttab.set_max_grants)
-		return 0;
-	return xcg->ops->u.gnttab.set_max_grants(xcg, xcg->ops_handle, count);
+    return osdep_gnttab_grant_map(xgt, 1, 0, prot,  &domid, &ref,
+                                  notify_offset, notify_port);
 }
 
 void *xc_gntshr_share_pages(xc_gntshr *xcg, uint32_t domid,
                             int count, uint32_t *refs, int writable)
 {
-	return xcg->ops->u.gntshr.share_pages(xcg, xcg->ops_handle, domid,
-	                                      count, refs, writable, -1, -1);
+    return osdep_gntshr_share_pages(xcg, domid, count, refs, writable, -1, -1);
 }
 
 void *xc_gntshr_share_page_notify(xc_gntshr *xcg, uint32_t domid,
@@ -213,22 +193,11 @@ void *xc_gntshr_share_page_notify(xc_gntshr *xcg, uint32_t domid,
                                   uint32_t notify_offset,
                                   evtchn_port_t notify_port)
 {
-	return xcg->ops->u.gntshr.share_pages(xcg, xcg->ops_handle,
-			domid, 1, ref, writable, notify_offset, notify_port);
+    return osdep_gntshr_share_pages(xcg, domid, 1, ref, writable,
+                                    notify_offset, notify_port);
 }
 
 /*
- * Unmaps the @count pages starting at @start_address, which were mapped by a
- * call to xc_gntshr_share_*. Never logs.
- */
-int xc_gntshr_munmap(xc_gntshr *xcg, void *start_address, uint32_t count)
-{
-	return xcg->ops->u.gntshr.munmap(xcg, xcg->ops_handle,
-					 start_address, count);
-}
-
-
-/*
  * Local variables:
  * mode: C
  * c-file-style: "BSD"
diff --git a/tools/libxc/xc_linux_osdep.c b/tools/libxc/xc_linux_osdep.c
index 2230e44..f2c7f10 100644
--- a/tools/libxc/xc_linux_osdep.c
+++ b/tools/libxc/xc_linux_osdep.c
@@ -42,6 +42,9 @@
 
 #define ROUNDUP(_x,_w) (((unsigned long)(_x)+(1UL<<(_w))-1) & ~((1UL<<(_w))-1))
 
+#define GTERROR(_l, _f...) xtl_log(_l, XTL_ERROR, errno, "gnttab", _f)
+#define GSERROR(_l, _f...) xtl_log(_l, XTL_ERROR, errno, "gntshr", _f)
+
 static xc_osdep_handle linux_privcmd_open(xc_interface *xch)
 {
     int flags, saved_errno;
@@ -455,26 +458,26 @@ static struct xc_osdep_ops linux_privcmd_ops = {
 
 #define DEVXEN "/dev/xen/"
 
-static xc_osdep_handle linux_gnttab_open(xc_gnttab *xcg)
+int osdep_gnttab_open(xc_gnttab *xgt)
 {
     int fd = open(DEVXEN "gntdev", O_RDWR);
-
     if ( fd == -1 )
-        return XC_OSDEP_OPEN_ERROR;
-
-    return (xc_osdep_handle)fd;
+        return -1;
+    xgt->fd = fd;
+    return 0;
 }
 
-static int linux_gnttab_close(xc_gnttab *xcg, xc_osdep_handle h)
+int osdep_gnttab_close(xc_gnttab *xgt)
 {
-    int fd = (int)h;
-    return close(fd);
+    if ( xgt->fd == -1 )
+        return 0;
+
+    return close(xgt->fd);
 }
 
-static int linux_gnttab_set_max_grants(xc_gnttab *xch, xc_osdep_handle h,
-                                       uint32_t count)
+int xc_gnttab_set_max_grants(xc_gnttab *xgt, uint32_t count)
 {
-    int fd = (int)h, rc;
+    int fd = xgt->fd, rc;
     struct ioctl_gntdev_set_max_grants max_grants = { .count = count };
 
     rc = ioctl(fd, IOCTL_GNTDEV_SET_MAX_GRANTS, &max_grants);
@@ -486,19 +489,19 @@ static int linux_gnttab_set_max_grants(xc_gnttab *xch, xc_osdep_handle h,
         if (errno == ENOTTY)
             rc = 0;
         else
-            PERROR("linux_gnttab_set_max_grants: ioctl SET_MAX_GRANTS failed");
+            GTERROR(xgt->logger, "ioctl SET_MAX_GRANTS failed");
     }
 
     return rc;
 }
 
-static void *linux_gnttab_grant_map(xc_gnttab *xch, xc_osdep_handle h,
-                                    uint32_t count, int flags, int prot,
-                                    uint32_t *domids, uint32_t *refs,
-                                    uint32_t notify_offset,
-                                    evtchn_port_t notify_port)
+void *osdep_gnttab_grant_map(xc_gnttab *xgt,
+                             uint32_t count, int flags, int prot,
+                             uint32_t *domids, uint32_t *refs,
+                             uint32_t notify_offset,
+                             evtchn_port_t notify_port)
 {
-    int fd = (int)h;
+    int fd = xgt->fd;
     struct ioctl_gntdev_map_grant_ref *map;
     unsigned int map_size = ROUNDUP((sizeof(*map) + (count - 1) *
                                     sizeof(struct ioctl_gntdev_map_grant_ref)),
@@ -519,7 +522,7 @@ static void *linux_gnttab_grant_map(xc_gnttab *xch, xc_osdep_handle h,
                    MAP_PRIVATE | MAP_ANON | MAP_POPULATE, -1, 0);
         if ( map == MAP_FAILED )
         {
-            PERROR("linux_gnttab_grant_map: mmap of map failed");
+            GTERROR(xgt->logger, "mmap of map failed");
             return NULL;
         }
     }
@@ -533,7 +536,7 @@ static void *linux_gnttab_grant_map(xc_gnttab *xch, xc_osdep_handle h,
     map->count = count;
 
     if ( ioctl(fd, IOCTL_GNTDEV_MAP_GRANT_REF, map) ) {
-        PERROR("linux_gnttab_grant_map: ioctl MAP_GRANT_REF failed");
+        GTERROR(xgt->logger, "ioctl MAP_GRANT_REF failed");
         goto out;
     }
 
@@ -572,7 +575,7 @@ static void *linux_gnttab_grant_map(xc_gnttab *xch, xc_osdep_handle h,
         if (notify.action)
             rv = ioctl(fd, IOCTL_GNTDEV_SET_UNMAP_NOTIFY, &notify);
         if (rv) {
-            PERROR("linux_gnttab_grant_map: ioctl SET_UNMAP_NOTIFY failed");
+            GTERROR(xgt->logger, "ioctl SET_UNMAP_NOTIFY failed");
             munmap(addr, count * XC_PAGE_SIZE);
             addr = MAP_FAILED;
         }
@@ -584,7 +587,7 @@ static void *linux_gnttab_grant_map(xc_gnttab *xch, xc_osdep_handle h,
         struct ioctl_gntdev_unmap_grant_ref unmap_grant;
 
         /* Unmap the driver slots used to store the grant information. */
-        PERROR("xc_gnttab_map_grant_refs: mmap failed");
+        GTERROR(xgt->logger, "mmap failed");
         unmap_grant.index = map->index;
         unmap_grant.count = count;
         ioctl(fd, IOCTL_GNTDEV_UNMAP_GRANT_REF, &unmap_grant);
@@ -599,12 +602,9 @@ static void *linux_gnttab_grant_map(xc_gnttab *xch, xc_osdep_handle h,
     return addr;
 }
 
-
-
-static int linux_gnttab_munmap(xc_gnttab *xcg, xc_osdep_handle h,
-                               void *start_address, uint32_t count)
+int xc_gnttab_munmap(xc_gnttab *xgt, void *start_address, uint32_t count)
 {
-    int fd = (int)h;
+    int fd = xgt->fd;
     struct ioctl_gntdev_get_offset_for_vaddr get_offset;
     struct ioctl_gntdev_unmap_grant_ref unmap_grant;
     int rc;
@@ -642,43 +642,33 @@ static int linux_gnttab_munmap(xc_gnttab *xcg, xc_osdep_handle h,
     return 0;
 }
 
-static struct xc_osdep_ops linux_gnttab_ops = {
-    .open = &linux_gnttab_open,
-    .close = &linux_gnttab_close,
-
-    .u.gnttab = {
-        .set_max_grants = linux_gnttab_set_max_grants,
-        .grant_map = &linux_gnttab_grant_map,
-        .munmap = &linux_gnttab_munmap,
-    },
-};
-
-static xc_osdep_handle linux_gntshr_open(xc_gntshr *xcg)
+int osdep_gntshr_open(xc_gntshr *xgs)
 {
     int fd = open(DEVXEN "gntalloc", O_RDWR);
-
     if ( fd == -1 )
-        return XC_OSDEP_OPEN_ERROR;
-
-    return (xc_osdep_handle)fd;
+        return -1;
+    xgs->fd = fd;
+    return 0;
 }
 
-static int linux_gntshr_close(xc_gntshr *xcg, xc_osdep_handle h)
+int osdep_gntshr_close(xc_gntshr *xgs)
 {
-    int fd = (int)h;
-    return close(fd);
+    if ( xgs->fd == -1 )
+        return 0;
+
+    return close(xgs->fd);
 }
 
-static void *linux_gntshr_share_pages(xc_gntshr *xch, xc_osdep_handle h,
-                                      uint32_t domid, int count,
-                                      uint32_t *refs, int writable,
-                                      uint32_t notify_offset,
-                                      evtchn_port_t notify_port)
+void *osdep_gntshr_share_pages(xc_gntshr *xgs,
+                               uint32_t domid, int count,
+                               uint32_t *refs, int writable,
+                               uint32_t notify_offset,
+                               evtchn_port_t notify_port)
 {
     struct ioctl_gntalloc_alloc_gref *gref_info = NULL;
     struct ioctl_gntalloc_unmap_notify notify;
     struct ioctl_gntalloc_dealloc_gref gref_drop;
-    int fd = (int)h;
+    int fd = xgs->fd;
     int err;
     void *area = NULL;
     gref_info = malloc(sizeof(*gref_info) + count * sizeof(uint32_t));
@@ -690,7 +680,7 @@ static void *linux_gntshr_share_pages(xc_gntshr *xch, xc_osdep_handle h,
 
     err = ioctl(fd, IOCTL_GNTALLOC_ALLOC_GREF, gref_info);
     if (err) {
-        PERROR("linux_gntshr_share_pages: ioctl failed");
+        GSERROR(xgs->logger, "ioctl failed");
         goto out;
     }
 
@@ -699,7 +689,7 @@ static void *linux_gntshr_share_pages(xc_gntshr *xch, xc_osdep_handle h,
 
     if (area == MAP_FAILED) {
         area = NULL;
-        PERROR("linux_gntshr_share_pages: mmap failed");
+        GSERROR(xgs->logger, "mmap failed");
         goto out_remove_fdmap;
     }
 
@@ -716,7 +706,7 @@ static void *linux_gntshr_share_pages(xc_gntshr *xch, xc_osdep_handle h,
     if (notify.action)
         err = ioctl(fd, IOCTL_GNTALLOC_SET_UNMAP_NOTIFY, &notify);
     if (err) {
-        PERROR("linux_gntshr_share_page_notify: ioctl SET_UNMAP_NOTIFY failed");
+        GSERROR(xgs->logger, "ioctl SET_UNMAP_NOTIFY failed");
 		munmap(area, count * XC_PAGE_SIZE);
 		area = NULL;
 	}
@@ -735,33 +725,18 @@ static void *linux_gntshr_share_pages(xc_gntshr *xch, xc_osdep_handle h,
     return area;
 }
 
-static int linux_gntshr_munmap(xc_gntshr *xcg, xc_osdep_handle h,
-                               void *start_address, uint32_t count)
+int xc_gntshr_munmap(xc_gntshr *xgs,
+                     void *start_address, uint32_t count)
 {
     return munmap(start_address, count * XC_PAGE_SIZE);
 }
 
-static struct xc_osdep_ops linux_gntshr_ops = {
-    .open = &linux_gntshr_open,
-    .close = &linux_gntshr_close,
-
-    .u.gntshr = {
-        .share_pages = &linux_gntshr_share_pages,
-        .munmap = &linux_gntshr_munmap,
-    },
-};
-
-
 static struct xc_osdep_ops *linux_osdep_init(xc_interface *xch, enum xc_osdep_type type)
 {
     switch ( type )
     {
     case XC_OSDEP_PRIVCMD:
         return &linux_privcmd_ops;
-    case XC_OSDEP_GNTTAB:
-        return &linux_gnttab_ops;
-    case XC_OSDEP_GNTSHR:
-        return &linux_gntshr_ops;
     default:
         return NULL;
     }
diff --git a/tools/libxc/xc_minios.c b/tools/libxc/xc_minios.c
index 7878cfa..2cc9ea9 100644
--- a/tools/libxc/xc_minios.c
+++ b/tools/libxc/xc_minios.c
@@ -203,19 +203,22 @@ void *xc_memalign(xc_interface *xch, size_t alignment, size_t size)
     return memalign(alignment, size);
 }
 
-static xc_osdep_handle minios_gnttab_open(xc_gnttab *xcg)
+int osdep_gnttab_open(xc_gnttab *xgt)
 {
     int fd = alloc_fd(FTYPE_GNTMAP);
     if ( fd == -1 )
-        return XC_OSDEP_OPEN_ERROR;
+        return -1;
     gntmap_init(&files[fd].gntmap);
-    return (xc_osdep_handle)fd;
+    xgt->fd = fd;
+    return 0;
 }
 
-static int minios_gnttab_close(xc_gnttab *xcg, xc_osdep_handle h)
+int osdep_gnttab_close(xc_gnttab *xgt)
 {
-    int fd = (int)h;
-    return close(fd);
+    if ( xgt->fd == -1 )
+        return 0;
+
+    return close(xgt->fd);
 }
 
 void minios_gnttab_close_fd(int fd)
@@ -224,13 +227,13 @@ void minios_gnttab_close_fd(int fd)
     files[fd].type = FTYPE_NONE;
 }
 
-static void *minios_gnttab_grant_map(xc_gnttab *xcg, xc_osdep_handle h,
-                                     uint32_t count, int flags, int prot,
-                                     uint32_t *domids, uint32_t *refs,
-                                     uint32_t notify_offset,
-                                     evtchn_port_t notify_port)
+void *osdep_gnttab_grant_map(xc_gnttab *xgt,
+                             uint32_t count, int flags, int prot,
+                             uint32_t *domids, uint32_t *refs,
+                             uint32_t notify_offset,
+                             evtchn_port_t notify_port)
 {
-    int fd = (int)h;
+    int fd = xgt->fd;
     int stride = 1;
     if (flags & XC_GRANT_MAP_SINGLE_DOMAIN)
         stride = 0;
@@ -243,11 +246,9 @@ static void *minios_gnttab_grant_map(xc_gnttab *xcg, xc_osdep_handle h,
                                  refs, prot & PROT_WRITE);
 }
 
-static int minios_gnttab_munmap(xc_gnttab *xcg, xc_osdep_handle h,
-                                void *start_address,
-                                uint32_t count)
+int xc_gnttab_munmap(xc_gnttab *xgt, void *start_address, uint32_t count)
 {
-    int fd = (int)h;
+    int fd = xgt->fd;
     int ret;
     ret = gntmap_munmap(&files[fd].gntmap,
                         (unsigned long) start_address,
@@ -259,10 +260,9 @@ static int minios_gnttab_munmap(xc_gnttab *xcg, xc_osdep_handle h,
     return ret;
 }
 
-static int minios_gnttab_set_max_grants(xc_gnttab *xcg, xc_osdep_handle h,
-                             uint32_t count)
+int xc_gnttab_set_max_grants(xc_gnttab *xgt, uint32_t count)
 {
-    int fd = (int)h;
+    int fd = xgt->fd;
     int ret;
     ret = gntmap_set_max_grants(&files[fd].gntmap,
                                 count);
@@ -273,25 +273,12 @@ static int minios_gnttab_set_max_grants(xc_gnttab *xcg, xc_osdep_handle h,
     return ret;
 }
 
-static struct xc_osdep_ops minios_gnttab_ops = {
-    .open = &minios_gnttab_open,
-    .close = &minios_gnttab_close,
-
-    .u.gnttab = {
-        .grant_map = &minios_gnttab_grant_map,
-        .munmap = &minios_gnttab_munmap,
-        .set_max_grants = &minios_gnttab_set_max_grants,
-    },
-};
-
 static struct xc_osdep_ops *minios_osdep_init(xc_interface *xch, enum xc_osdep_type type)
 {
     switch ( type )
     {
     case XC_OSDEP_PRIVCMD:
         return &minios_privcmd_ops;
-    case XC_OSDEP_GNTTAB:
-        return &minios_gnttab_ops;
     default:
         return NULL;
     }
diff --git a/tools/libxc/xc_nogntshr.c b/tools/libxc/xc_nogntshr.c
new file mode 100644
index 0000000..6681018
--- /dev/null
+++ b/tools/libxc/xc_nogntshr.c
@@ -0,0 +1,44 @@
+/******************************************************************************
+ *
+ * Copyright (c) 2007-2008, D G Murray <Derek.Murray@cl.cam.ac.uk>
+ *
+ * This library 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 of the License.
+ *
+ * This library 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 <stdlib.h>
+
+#include "xc_private.h"
+
+int osdep_gntshr_open(xc_gnttab *xgt)
+{
+    return -1;
+}
+
+int osdep_gntshr_close(xc_gnttab *xgt)
+{
+    return 0;
+}
+
+void *osdep_gntshr_share_pages(xc_gntshr *xgs,
+                               uint32_t domid, int count,
+                               uint32_t *refs, int writable,
+                               uint32_t notify_offset,
+                               evtchn_port_t notify_port)
+{
+    abort()
+}
+
+int xc_gntshr_munmap(xc_gntshr *xgs,
+                     void *start_address, uint32_t count)
+{
+    abort();
+}
diff --git a/tools/libxc/xc_nognttab.c b/tools/libxc/xc_nognttab.c
new file mode 100644
index 0000000..4b4a2ca
--- /dev/null
+++ b/tools/libxc/xc_nognttab.c
@@ -0,0 +1,48 @@
+/******************************************************************************
+ *
+ * Copyright (c) 2007-2008, D G Murray <Derek.Murray@cl.cam.ac.uk>
+ *
+ * This library 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 of the License.
+ *
+ * This library 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 <stdlib.h>
+
+#include "xc_private.h"
+
+int osdep_gnttab_open(xc_gnttab *xgt)
+{
+    return -1;
+}
+
+int osdep_gnttab_close(xc_gnttab *xgt)
+{
+    return 0;
+}
+
+int xc_gnttab_set_max_grants(xc_gnttab *xgt, uint32_t count)
+{
+    abort();
+}
+
+void *osdep_gnttab_grant_map(xc_gnttab *xgt,
+                             uint32_t count, int flags, int prot,
+                             uint32_t *domids, uint32_t *refs,
+                             uint32_t notify_offset,
+                             evtchn_port_t notify_port)
+{
+    abort();
+}
+
+int xc_gnttab_munmap(xc_gnttab *xgt, void *start_address, uint32_t count)
+{
+    abort();
+}
diff --git a/tools/libxc/xc_private.c b/tools/libxc/xc_private.c
index 375430c..b2c3c06 100644
--- a/tools/libxc/xc_private.c
+++ b/tools/libxc/xc_private.c
@@ -120,8 +120,6 @@ static const char *xc_osdep_type_name(enum xc_osdep_type type)
     switch ( type )
     {
     case XC_OSDEP_PRIVCMD: return "privcmd";
-    case XC_OSDEP_GNTTAB:  return "gnttab";
-    case XC_OSDEP_GNTSHR:  return "gntshr";
     }
     return "unknown";
 }
@@ -252,30 +250,85 @@ int do_xen_hypercall(xc_interface *xch, privcmd_hypercall_t *hypercall)
     return xch->ops->u.privcmd.hypercall(xch, xch->ops_handle, hypercall);
 }
 
-xc_gnttab *xc_gnttab_open(xentoollog_logger *logger,
-                             unsigned open_flags)
+xc_gnttab *xc_gnttab_open(xentoollog_logger *logger, unsigned open_flags)
 {
-    return xc_interface_open_common(logger, NULL, open_flags,
-                                    XC_OSDEP_GNTTAB);
+    xc_gnttab *xgt = malloc(sizeof(*xgt));
+    int rc;
+
+    if (!xgt) return NULL;
+
+    xgt->fd = -1;
+    xgt->logger = logger;
+    xgt->logger_tofree  = NULL;
+
+    if (!xgt->logger) {
+        xgt->logger = xgt->logger_tofree =
+            (xentoollog_logger*)
+            xtl_createlogger_stdiostream(stderr, XTL_PROGRESS, 0);
+        if (!xgt->logger) goto err;
+    }
+
+    rc = osdep_gnttab_open(xgt);
+    if ( rc  < 0 ) goto err;
+
+    return xgt;
+
+err:
+    osdep_gnttab_close(xgt);
+    xtl_logger_destroy(xgt->logger_tofree);
+    free(xgt);
+    return NULL;
 }
 
-int xc_gnttab_close(xc_gnttab *xcg)
+int xc_gnttab_close(xc_gnttab *xgt)
 {
-    return xc_interface_close_common(xcg);
+    int rc;
+
+    rc = osdep_gnttab_close(xgt);
+    xtl_logger_destroy(xgt->logger_tofree);
+    free(xgt);
+    return rc;
 }
 
-xc_gntshr *xc_gntshr_open(xentoollog_logger *logger,
-                             unsigned open_flags)
+xc_gntshr *xc_gntshr_open(xentoollog_logger *logger, unsigned open_flags)
 {
-    return xc_interface_open_common(logger, NULL, open_flags,
-                                    XC_OSDEP_GNTSHR);
+    xc_gntshr *xgs = malloc(sizeof(*xgs));
+    int rc;
+
+    if (!xgs) return NULL;
+
+    xgs->fd = -1;
+    xgs->logger = logger;
+    xgs->logger_tofree  = NULL;
+
+    if (!xgs->logger) {
+        xgs->logger = xgs->logger_tofree =
+            (xentoollog_logger*)
+            xtl_createlogger_stdiostream(stderr, XTL_PROGRESS, 0);
+        if (!xgs->logger) goto err;
+    }
+
+    rc = osdep_gntshr_open(xgs);
+    if ( rc  < 0 ) goto err;
+
+    return xgs;
+
+err:
+    osdep_gntshr_close(xgs);
+    xtl_logger_destroy(xgs->logger_tofree);
+    free(xgs);
+    return NULL;
 }
 
-int xc_gntshr_close(xc_gntshr *xcg)
+int xc_gntshr_close(xc_gntshr *xgs)
 {
-    return xc_interface_close_common(xcg);
-}
+    int rc;
 
+    rc = osdep_gntshr_close(xgs);
+    xtl_logger_destroy(xgs->logger_tofree);
+    free(xgs);
+    return rc;
+}
 
 static pthread_key_t errbuf_pkey;
 static pthread_once_t errbuf_pkey_once = PTHREAD_ONCE_INIT;
diff --git a/tools/libxc/xc_private.h b/tools/libxc/xc_private.h
index 61f2f45..81af034 100644
--- a/tools/libxc/xc_private.h
+++ b/tools/libxc/xc_private.h
@@ -124,6 +124,30 @@ struct xc_interface_core {
     xc_osdep_handle  ops_handle; /* opaque data for xc_osdep_ops */
 };
 
+struct xengntdev_handle {
+    xentoollog_logger *logger, *logger_tofree;
+    int fd;
+};
+
+int osdep_gnttab_open(xc_gnttab *xgt);
+int osdep_gnttab_close(xc_gnttab *xgt);
+
+#define XC_GRANT_MAP_SINGLE_DOMAIN 0x1
+void *osdep_gnttab_grant_map(xc_gnttab *xgt,
+                             uint32_t count, int flags, int prot,
+                             uint32_t *domids, uint32_t *refs,
+                             uint32_t notify_offset,
+                             evtchn_port_t notify_port);
+
+int osdep_gntshr_open(xc_gntshr *xgs);
+int osdep_gntshr_close(xc_gntshr *xgs);
+
+void *osdep_gntshr_share_pages(xc_gntshr *xgs,
+                               uint32_t domid, int count,
+                               uint32_t *refs, int writable,
+                               uint32_t notify_offset,
+                               evtchn_port_t notify_port);
+
 void xc_report_error(xc_interface *xch, int code, const char *fmt, ...)
     __attribute__((format(printf,3,4)));
 void xc_reportv(xc_interface *xch, xentoollog_logger *lg, xentoollog_level,
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH XEN v2 08/15] tools: Refactor /dev/xen/gnt{dev, shr} wrappers into libxengnttab.
  2015-07-15 15:46 [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries Ian Campbell
                   ` (6 preceding siblings ...)
  2015-07-15 15:46 ` [PATCH XEN v2 07/15] tools/libxc: Remove osdep indirection for xc_gnt{shr, tab} Ian Campbell
@ 2015-07-15 15:46 ` Ian Campbell
  2015-09-22 11:25   ` Ian Campbell
  2015-07-15 15:46 ` [PATCH XEN v2 09/15] tools/libxc: Remove osdep indirection for privcmd Ian Campbell
                   ` (19 subsequent siblings)
  27 siblings, 1 reply; 55+ messages in thread
From: Ian Campbell @ 2015-07-15 15:46 UTC (permalink / raw)
  To: ian.jackson, wei.liu2, xen-devel
  Cc: roger.pau, Ian Campbell, stefano.stabellini

libxengnttab will provide a stable API and ABI for accessing the
grant table devices.

The functions are moved into the xengnt{tab,shr} namespace to make a
clean break from libxc and avoid ambiguity regarding which interfaces
are stable.

XXX consider combining into a single namespace (i.e. with
xengnttab_handle having two open fd's in it on Linux)

All in-tree users are updated to use the new names.

Upon request (via #define XC_WANT_COMPAT_GNTTAB_API) libxenctrl will
provide a compat API for the old names. This is used by qemu-xen for
the time being. qemu-xen-traditional is updated in lockstep.

This leaves a few grant table related functions which go via privcmd
(EVTCHNOP) rather than ioctls on the /dev/xen/gnt* devices in
libxenctrl. Specifically:

  - xc_gnttab_get_version
  - xc_gnttab_map_table_v1
  - xc_gnttab_map_table_v2
  - xc_gnttab_op

These functions do not appear to be needed by qemu-dm, qemu-pv
(provision of device model to HVM guests and PV backends respectively)
or by libvchan suggesting they are not needed by non-toolstack uses of
event channels.

The new library uses a version script to ensure that only expected
symbols are exported and to version them such that ABI guarantees can
be kept in the future.

After this change libxenvchan no longer needs to link against
libxenctrl. It still needs xenctrl.h in one file for xen_mb and
friends.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
---

Must be applied with:

 - "qemu-xen-traditional: Use libxengnttab" and a corresponding
   QEMU_TAG update folded here.
 - "mini-os: Include libxengnttab with libxc"" and a corresponding
   bump to MINIOS_UPSTREAM_REVISION folded in here.
---
 .gitignore                              |   2 +
 docs/misc/toolstack-library-abis.pandoc |  38 ++--
 stubdom/Makefile                        |  19 +-
 tools/Makefile                          |   4 +
 tools/Rules.mk                          |  14 +-
 tools/console/Makefile                  |   5 +-
 tools/console/daemon/io.c               |  21 +-
 tools/libvchan/Makefile                 |   8 +-
 tools/libvchan/init.c                   |  24 +--
 tools/libvchan/io.c                     |   8 +-
 tools/libvchan/libxenvchan.h            |   6 +-
 tools/libxc/Makefile                    |  15 +-
 tools/libxc/include/xenctrl.h           | 168 ----------------
 tools/libxc/include/xenctrl_compat.h    |  48 +++++
 tools/libxc/xc_gnttab.c                 |  53 ------
 tools/libxc/xc_gnttab_compat.c          | 111 +++++++++++
 tools/libxc/xc_linux_osdep.c            | 280 ---------------------------
 tools/libxc/xc_minios.c                 |  73 -------
 tools/libxc/xc_nogntshr.c               |  44 -----
 tools/libxc/xc_nognttab.c               |  48 -----
 tools/libxc/xc_private.c                |  80 --------
 tools/libxc/xc_private.h                |  24 ---
 tools/libxenevtchn/minios.c             |   5 +-
 tools/libxengnttab/Makefile             |  69 +++++++
 tools/libxengnttab/gntshr_core.c        |  89 +++++++++
 tools/libxengnttab/gntshr_unimp.c       |  59 ++++++
 tools/libxengnttab/gnttab_core.c        | 118 ++++++++++++
 tools/libxengnttab/gnttab_unimp.c       |  86 +++++++++
 tools/libxengnttab/include/xengnttab.h  | 215 +++++++++++++++++++++
 tools/libxengnttab/libxengnttab.map     |  23 +++
 tools/libxengnttab/linux.c              | 326 ++++++++++++++++++++++++++++++++
 tools/libxengnttab/minios.c             | 114 +++++++++++
 tools/libxengnttab/private.h            |  47 +++++
 tools/xenstore/Makefile                 |   4 +-
 tools/xenstore/xenstored_core.h         |   4 +-
 tools/xenstore/xenstored_domain.c       |  24 +--
 tools/xenstore/xenstored_minios.c       |   5 +-
 37 files changed, 1432 insertions(+), 849 deletions(-)
 create mode 100644 tools/libxc/xc_gnttab_compat.c
 delete mode 100644 tools/libxc/xc_nogntshr.c
 delete mode 100644 tools/libxc/xc_nognttab.c
 create mode 100644 tools/libxengnttab/Makefile
 create mode 100644 tools/libxengnttab/gntshr_core.c
 create mode 100644 tools/libxengnttab/gntshr_unimp.c
 create mode 100644 tools/libxengnttab/gnttab_core.c
 create mode 100644 tools/libxengnttab/gnttab_unimp.c
 create mode 100644 tools/libxengnttab/include/xengnttab.h
 create mode 100644 tools/libxengnttab/libxengnttab.map
 create mode 100644 tools/libxengnttab/linux.c
 create mode 100644 tools/libxengnttab/minios.c
 create mode 100644 tools/libxengnttab/private.h

diff --git a/.gitignore b/.gitignore
index 61167d9..8cbd177 100644
--- a/.gitignore
+++ b/.gitignore
@@ -61,6 +61,7 @@ stubdom/ioemu
 stubdom/xenstore
 stubdom/libxentoollog-*
 stubdom/libxenevtchn-*
+stubdom/libxengnttab-*
 stubdom/libxc-*
 stubdom/lwip-*
 stubdom/mini-os-*
@@ -89,6 +90,7 @@ config/Stubdom.mk
 config/Docs.mk
 tools/libxentoollog/headers.chk
 tools/libxenevtchn/headers.chk
+tools/libxengnttab/headers.chk
 tools/blktap2/daemon/blktapctrl
 tools/blktap2/drivers/img2qcow
 tools/blktap2/drivers/lock-util
diff --git a/docs/misc/toolstack-library-abis.pandoc b/docs/misc/toolstack-library-abis.pandoc
index d7ae875..6b6146a 100644
--- a/docs/misc/toolstack-library-abis.pandoc
+++ b/docs/misc/toolstack-library-abis.pandoc
@@ -128,6 +128,29 @@ Interface                     Underlying interface             Known external us
 `xenevtchn_unbind`            `IOCTL_EVTCHN_UNBIND`            qemu-pv
 `xenevtchn_unmask`            `write(2)`                       qemu-dm, qemu-pv
 
+## `libxengnttab`: grant tables
+
+Interacting with Grant Tables via `/dev/xen/gnt{shr,alloc}`.
+
+Interface                         Underlying interface           Known external users
+--------------------------------- ------------------------------ --------------------
+`xengnttab_map_domain_grant_refs` `IOCTL_GNTDEV_SET_MAX_GRANTS`
+`xengnttab_map_grant_ref_notify`  `IOCTL_GNTDEV_MAP_GRANT_REF`
+`xengnttab_map_grant_ref`         `IOCTL_GNTDEV_MAP_GRANT_REF`   qemu-pv
+`xengnttab_map_grant_refs`        `IOCTL_GNTDEV_SET_MAX_GRANTS`  qemu-pv
+`xengnttab_munmap`                `munmap(2)`                    qemu-pv
+`xengnttab_open`                  `open(2)`                      qemu-pv
+`xengnttab_close`                 `close(2)`                     qemu-pv
+`xengnttab_set_max_grants`        `IOCTL_GNTDEV_SET_MAX_GRANTS`
+`xengntshr_close`                 `close(2)`
+`xengntshr_munmap`                `munmap(2)`
+`xengntshr_open`                  `open(2)`
+`xengntshr_share_page_notify`     `IOCTL_GNTALLOC_ALLOC_GREF`
+`xengntshr_share_pages`           `IOCTL_GNTALLOC_ALLOC_GREF`
+
+`xengnt???_*_notify` also use `IOCTL_GNTALLOC_SET_UNMAP_NOTIFY`,
+`IOCTL_GNTALLOC_SET_UNMAP_NOTIFY`, etc
+
 # Unstable libraries
 
 These libraries do not provide a stable interface and are required to
@@ -181,23 +204,10 @@ Interface                     Underlying interface             Known external us
 ### Grant tables
 
 Interacting with Grant Tables via `__HYPERVISOR_grant_table_op`
-(`GNTTABOP_*`) or `/dev/xen/gnt{shr,alloc}`.
+(`GNTTABOP_*`)`.
 
 Interface                         Underlying interface           Known external users
 --------------------------------- ------------------------------ --------------------
-`xc_gnttab_map_domain_grant_refs` `IOCTL_GNTDEV_SET_MAX_GRANTS`
-`xc_gnttab_map_grant_ref_notify`  `IOCTL_GNTDEV_MAP_GRANT_REF`
-`xc_gnttab_map_grant_ref`         `IOCTL_GNTDEV_MAP_GRANT_REF`   qemu-pv
-`xc_gnttab_map_grant_refs`        `IOCTL_GNTDEV_SET_MAX_GRANTS`  qemu-pv
-`xc_gnttab_munmap`                `munmap(2)`                    qemu-pv
-`xc_gnttab_open`                  `open(2)`                      qemu-pv
-`xc_gnttab_close`                 `close(2)`                     qemu-pv
-`xc_gnttab_set_max_grants`        `IOCTL_GNTDEV_SET_MAX_GRANTS`
-`xc_gntshr_close`                 `close(2)`
-`xc_gntshr_munmap`                `munmap(2)`
-`xc_gntshr_open`                  `open(2)`
-`xc_gntshr_share_page_notify`     `IOCTL_GNTALLOC_ALLOC_GREF`
-`xc_gntshr_share_pages`           `IOCTL_GNTALLOC_ALLOC_GREF`
 `xc_gnttab_op`                    `__HYPERVISOR_grant_table_op`
 `xc_gnttab_get_version`           `GNTTABOP_get_version`
 `xc_gnttab_map_table_v1`          `GNTTABOP_setup_table`
diff --git a/stubdom/Makefile b/stubdom/Makefile
index b4dd39a..7eab97f 100644
--- a/stubdom/Makefile
+++ b/stubdom/Makefile
@@ -324,6 +324,12 @@ mk-headers-$(XEN_TARGET_ARCH): $(IOEMU_LINKFARM_TARGET)
 	  ln -sf $(XEN_ROOT)/tools/libxenevtchn/include/*.h include/ && \
 	  ln -sf $(XEN_ROOT)/tools/libxenevtchn/*.c . && \
 	  ln -sf $(XEN_ROOT)/tools/libxenevtchn/Makefile . )
+	mkdir -p libxengnttab-$(XEN_TARGET_ARCH)/include
+	[ -h libxengnttab-$(XEN_TARGET_ARCH)/Makefile ] || ( cd libxengnttab-$(XEN_TARGET_ARCH) && \
+	  ln -sf $(XEN_ROOT)/tools/libxengnttab/*.h . && \
+	  ln -sf $(XEN_ROOT)/tools/libxengnttab/include/*.h include/ && \
+	  ln -sf $(XEN_ROOT)/tools/libxengnttab/*.c . && \
+	  ln -sf $(XEN_ROOT)/tools/libxengnttab/Makefile . )
 	mkdir -p libxc-$(XEN_TARGET_ARCH)
 	[ -h libxc-$(XEN_TARGET_ARCH)/Makefile ] || ( cd libxc-$(XEN_TARGET_ARCH) && \
 	  ln -sf $(XEN_ROOT)/tools/libxc/*.h . && \
@@ -369,12 +375,23 @@ libxenevtchn-$(XEN_TARGET_ARCH)/libxenevtchn.a: $(NEWLIB_STAMPFILE)
 	CPPFLAGS="$(TARGET_CPPFLAGS)" CFLAGS="$(TARGET_CFLAGS)" $(MAKE) DESTDIR= -C libxenevtchn-$(XEN_TARGET_ARCH)
 
 #######
+# libxengnttab
+#######
+
+.PHONY: libxengnttab
+libxengnttab: libxengnttab-$(XEN_TARGET_ARCH)/libxengnttab.a
+libxengnttab-$(XEN_TARGET_ARCH)/libxengnttab.a: $(NEWLIB_STAMPFILE)
+	$(MAKE) -C $(XEN_ROOT)/tools/include
+	$(MAKE) DESTDIR= -C $(MINI_OS) links
+	CPPFLAGS="$(TARGET_CPPFLAGS)" CFLAGS="$(TARGET_CFLAGS)" $(MAKE) DESTDIR= -C libxengnttab-$(XEN_TARGET_ARCH)
+
+#######
 # libxc
 #######
 
 .PHONY: libxc
 libxc: libxc-$(XEN_TARGET_ARCH)/libxenctrl.a libxc-$(XEN_TARGET_ARCH)/libxenguest.a
-libxc-$(XEN_TARGET_ARCH)/libxenctrl.a: libxentoollog libxenevtchn cross-zlib
+libxc-$(XEN_TARGET_ARCH)/libxenctrl.a: libxentoollog libxenevtchn libxengnttab cross-zlib
 	$(MAKE) -C $(XEN_ROOT)/tools/include
 	$(MAKE) DESTDIR= -C $(MINI_OS) links
 	CPPFLAGS="$(TARGET_CPPFLAGS)" CFLAGS="$(TARGET_CFLAGS)" $(MAKE) DESTDIR= CONFIG_LIBXC_MINIOS=y -C libxc-$(XEN_TARGET_ARCH)
diff --git a/tools/Makefile b/tools/Makefile
index 3497c53..d3bf571 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -5,6 +5,7 @@ SUBDIRS-y :=
 SUBDIRS-y += include
 SUBDIRS-y += libxentoollog
 SUBDIRS-y += libxenevtchn
+SUBDIRS-y += libxengnttab
 SUBDIRS-y += libxc
 SUBDIRS-$(FLASK_ENABLE) += flask
 SUBDIRS-y += xenstore
@@ -250,9 +251,11 @@ subdir-all-qemu-xen-dir: qemu-xen-dir-find
 		--includedir=$(LIBEXEC_INC) \
 		--source-path=$$source \
 		--extra-cflags="-DXC_WANT_COMPAT_EVTCHN_API=1 \
+		-DXC_WANT_COMPAT_GNTTAB_API=1 \
 		-I$(XEN_ROOT)/tools/include \
 		-I$(XEN_ROOT)/tools/libxentoollog/include \
 		-I$(XEN_ROOT)/tools/libxenevtchn/include \
+		-I$(XEN_ROOT)/tools/libxengnttab/include \
 		-I$(XEN_ROOT)/tools/libxc/include \
 		-I$(XEN_ROOT)/tools/xenstore/include \
 		-I$(XEN_ROOT)/tools/xenstore/compat/include \
@@ -261,6 +264,7 @@ subdir-all-qemu-xen-dir: qemu-xen-dir-find
 		-L$(XEN_ROOT)/tools/xenstore \
 		-Wl,-rpath-link=$(XEN_ROOT)/tools/libxentoollog \
 		-Wl,-rpath-link=$(XEN_ROOT)/tools/libxenevtchn \
+		-Wl,-rpath-link=$(XEN_ROOT)/tools/libxengnttab \
 		$(QEMU_UPSTREAM_RPATH)" \
 		--bindir=$(LIBEXEC_BIN) \
 		--datadir=$(SHAREDIR)/qemu-xen \
diff --git a/tools/Rules.mk b/tools/Rules.mk
index f675fa7..e3923e2 100644
--- a/tools/Rules.mk
+++ b/tools/Rules.mk
@@ -12,6 +12,7 @@ INSTALL = $(XEN_ROOT)/tools/cross-install
 XEN_INCLUDE        = $(XEN_ROOT)/tools/include
 XEN_LIBXENTOOLLOG  = $(XEN_ROOT)/tools/libxentoollog
 XEN_LIBXENEVTCHN   = $(XEN_ROOT)/tools/libxenevtchn
+XEN_LIBXENGNTTAB   = $(XEN_ROOT)/tools/libxengnttab
 XEN_LIBXC          = $(XEN_ROOT)/tools/libxc
 XEN_XENLIGHT       = $(XEN_ROOT)/tools/libxl
 XEN_XENSTORE       = $(XEN_ROOT)/tools/xenstore
@@ -88,8 +89,17 @@ SHDEPS_libxenevtchn =
 LDLIBS_libxenevtchn = $(XEN_LIBXENEVTCHN)/libxenevtchn$(libextension)
 SHLIB_libxenevtchn  = -Wl,-rpath-link=$(XEN_LIBXENEVTCHN)
 
+CFLAGS_libxengnttab = -I$(XEN_LIBXENGNTTAB)/include $(CFLAGS_xeninclude)
+LDLIBS_libxengnttab = $(XEN_LIBXENGNTTAB)/libxengnttab$(libextension)
+SHLIB_libxengnttab  = -Wl,-rpath-link=$(XEN_LIBXENGNTTAB)
+
+# xengntshr_* interfaces are actually part of libxengnttab.so
+CFLAGS_libxengntshr = -I$(XEN_LIBXENGNTTAB)/include $(CFLAGS_xeninclude)
+LDLIBS_libxengntshr = $(XEN_LIBXENGNTTAB)/libxengnttab$(libextension)
+SHLIB_libxengntshr  = -Wl,-rpath-link=$(XEN_LIBXENGNTTAB)
+
 CFLAGS_libxenctrl = -I$(XEN_LIBXC)/include $(CFLAGS_libxentoollog) $(CFLAGS_xeninclude)
-SHDEPS_libxenctrl = $(SHLIB_libxentoollog) $(SHLIB_libxenevtchn)
+SHDEPS_libxenctrl = $(SHLIB_libxentoollog) $(SHLIB_libxenevtchn) $(SHLIB_libxengnttab) $(SHLIB_libxengntshr)
 LDLIBS_libxenctrl = $(SHDEPS_libxenctrl) $(XEN_LIBXC)/libxenctrl$(libextension)
 SHLIB_libxenctrl  = $(SHDEPS_libxenctrl) -Wl,-rpath-link=$(XEN_LIBXC)
 
@@ -109,7 +119,7 @@ LDLIBS_libxenstat  = $(SHDEPS_libxenstat) $(XEN_LIBXENSTAT)/libxenstat$(libexten
 SHLIB_libxenstat   = $(SHDEPS_libxenstat) -Wl,-rpath-link=$(XEN_LIBXENSTAT)
 
 CFLAGS_libxenvchan = -I$(XEN_LIBVCHAN)
-SHDEPS_libxenvchan = $(SHLIB_libxenctrl) $(SHLIB_libxenstore) $(SHLIB_libxenevtchn)
+SHDEPS_libxenvchan = $(SHLIB_libxenctrl) $(SHLIB_libxenstore) $(SHLIB_libxenevtchn) $(SHLIB_libxengnttab) $(SHLIB_libxengntshr)
 LDLIBS_libxenvchan = $(SHDEPS_libxenvchan) $(XEN_LIBVCHAN)/libxenvchan$(libextension)
 SHLIB_libxenvchan  = $(SHDEPS_libxenvchan) -Wl,-rpath-link=$(XEN_LIBVCHAN)
 
diff --git a/tools/console/Makefile b/tools/console/Makefile
index 0141d7f..1d4b6ae 100644
--- a/tools/console/Makefile
+++ b/tools/console/Makefile
@@ -3,10 +3,8 @@ include $(XEN_ROOT)/tools/Rules.mk
 
 CFLAGS  += -Werror
 
-CFLAGS  += $(CFLAGS_libxenevtchn)
 CFLAGS  += $(CFLAGS_libxenctrl)
 CFLAGS  += $(CFLAGS_libxenstore)
-LDLIBS += $(LDLIBS_libxenevtchn)
 LDLIBS += $(LDLIBS_libxenctrl)
 LDLIBS += $(LDLIBS_libxenstore)
 LDLIBS += $(SOCKET_LIBS)
@@ -27,8 +25,9 @@ clean:
 .PHONY: distclean
 distclean: clean
 
+daemon/io.o: CFLAGS += $(CFLAGS_libxenevtchn) $(CFLAGS_libxengnttab)
 xenconsoled: $(patsubst %.c,%.o,$(wildcard daemon/*.c))
-	$(CC) $(LDFLAGS) $^ -o $@ $(LDLIBS) $(LDLIBS_xenconsoled) $(APPEND_LDFLAGS)
+	$(CC) $(LDFLAGS) $^ -o $@ $(LDLIBS) $(LDLIBS_libxenevtchn) $(LDLIBS_libxengnttab) $(LDLIBS_xenconsoled) $(APPEND_LDFLAGS)
 
 xenconsole: $(patsubst %.c,%.o,$(wildcard client/*.c))
 	$(CC) $(LDFLAGS) $^ -o $@ $(LDLIBS) $(LDLIBS_xenconsole) $(APPEND_LDFLAGS)
diff --git a/tools/console/daemon/io.c b/tools/console/daemon/io.c
index 8829b09..7f2f861 100644
--- a/tools/console/daemon/io.c
+++ b/tools/console/daemon/io.c
@@ -23,6 +23,7 @@
 #include "utils.h"
 #include "io.h"
 #include <xenevtchn.h>
+#include <xengnttab.h>
 #include <xenstore.h>
 #include <xen/io/console.h>
 #include <xen/grant_table.h>
@@ -73,7 +74,7 @@ static int log_time_hv_needts = 1;
 static int log_time_guest_needts = 1;
 static int log_hv_fd = -1;
 
-static xc_gnttab *xcg_handle = NULL;
+static xengnttab_handle *xgt_handle = NULL;
 
 static struct pollfd  *fds;
 static unsigned int current_array_size;
@@ -521,8 +522,8 @@ static void domain_unmap_interface(struct domain *dom)
 {
 	if (dom->interface == NULL)
 		return;
-	if (xcg_handle && dom->ring_ref == -1)
-		xc_gnttab_munmap(xcg_handle, dom->interface, 1);
+	if (xgt_handle && dom->ring_ref == -1)
+		xengnttab_munmap(xgt_handle, dom->interface, 1);
 	else
 		munmap(dom->interface, XC_PAGE_SIZE);
 	dom->interface = NULL;
@@ -553,9 +554,9 @@ static int domain_create_ring(struct domain *dom)
 	if (ring_ref != dom->ring_ref && dom->ring_ref != -1)
 		domain_unmap_interface(dom);
 
-	if (!dom->interface && xcg_handle) {
+	if (!dom->interface && xgt_handle) {
 		/* Prefer using grant table */
-		dom->interface = xc_gnttab_map_grant_ref(xcg_handle,
+		dom->interface = xengnttab_map_grant_ref(xgt_handle,
 			dom->domid, GNTTAB_RESERVED_CONSOLE,
 			PROT_READ|PROT_WRITE);
 		dom->ring_ref = -1;
@@ -1030,8 +1031,8 @@ void handle_io(void)
 		handle_hv_logs(xce_handle, true);
 	}
 
-	xcg_handle = xc_gnttab_open(NULL, 0);
-	if (xcg_handle == NULL) {
+	xgt_handle = xengnttab_open(NULL, 0);
+	if (xgt_handle == NULL) {
 		dolog(LOG_DEBUG, "Failed to open xcg handle: %d (%s)",
 		      errno, strerror(errno));
 	}
@@ -1207,9 +1208,9 @@ void handle_io(void)
 		xenevtchn_close(xce_handle);
 		xce_handle = NULL;
 	}
-	if (xcg_handle != NULL) {
-		xc_gnttab_close(xcg_handle);
-		xcg_handle = NULL;
+	if (xgt_handle != NULL) {
+		xengnttab_close(xgt_handle);
+		xgt_handle = NULL;
 	}
 	log_hv_evtchn = -1;
 }
diff --git a/tools/libvchan/Makefile b/tools/libvchan/Makefile
index 84128a3..0573d2f 100644
--- a/tools/libvchan/Makefile
+++ b/tools/libvchan/Makefile
@@ -10,15 +10,17 @@ NODE_OBJS = node.o
 NODE2_OBJS = node-select.o
 
 LIBVCHAN_PIC_OBJS = $(patsubst %.o,%.opic,$(LIBVCHAN_OBJS))
-LIBVCHAN_LIBS = $(LDLIBS_libxenstore) $(LDLIBS_libxenctrl) $(LDLIBS_libxenevtchn)
-$(LIBVCHAN_OBJS) $(LIBVCHAN_PIC_OBJS): CFLAGS += $(CFLAGS_libxenstore) $(CFLAGS_libxenctrl) $(CFLAGS_libxenevtchn)
-$(NODE_OBJS) $(NODE2_OBJS): CFLAGS += $(CFLAGS_libxenctrl) $(CFLAGS_libxenevtchn)
+LIBVCHAN_LIBS = $(LDLIBS_libxenstore) $(LDLIBS_libxengnttab) $(LDLIBS_libxengntshr) $(LDLIBS_libxenevtchn)
+$(LIBVCHAN_OBJS) $(LIBVCHAN_PIC_OBJS): CFLAGS += $(CFLAGS_libxenstore) $(CFLAGS_libxengnttab) $(CFLAGS_libxengntshr) $(CFLAGS_libxenevtchn)
+$(NODE_OBJS) $(NODE2_OBJS): CFLAGS += $(CFLAGS_libxengnttab) $(CFLAGS_libxengntshr) $(CFLAGS_libxenevtchn)
 
 MAJOR = 1.0
 MINOR = 0
 
 CFLAGS += -I../include -I.
 
+io.o io.opic: CFLAGS += $(CFLAGS_libxenctrl) # for xen_mb et al
+
 .PHONY: all
 all: libxenvchan.so vchan-node1 vchan-node2 libxenvchan.a
 
diff --git a/tools/libvchan/init.c b/tools/libvchan/init.c
index fef6c8d..d1c1191 100644
--- a/tools/libvchan/init.c
+++ b/tools/libvchan/init.c
@@ -79,7 +79,7 @@ static int init_gnt_srv(struct libxenvchan *ctrl, int domain)
 	uint32_t ring_ref = -1;
 	void *ring;
 
-	ring = xc_gntshr_share_page_notify(ctrl->gntshr, domain,
+	ring = xengntshr_share_page_notify(ctrl->gntshr, domain,
 			&ring_ref, 1, offsetof(struct vchan_interface, srv_live),
 			ctrl->event_port);
 
@@ -105,7 +105,7 @@ static int init_gnt_srv(struct libxenvchan *ctrl, int domain)
 		ctrl->read.buffer = ((void*)ctrl->ring) + LARGE_RING_OFFSET;
 		break;
 	default:
-		ctrl->read.buffer = xc_gntshr_share_pages(ctrl->gntshr, domain,
+		ctrl->read.buffer = xengntshr_share_pages(ctrl->gntshr, domain,
 			pages_left, ctrl->ring->grants, 1);
 		if (!ctrl->read.buffer)
 			goto out_ring;
@@ -119,7 +119,7 @@ static int init_gnt_srv(struct libxenvchan *ctrl, int domain)
 		ctrl->write.buffer = ((void*)ctrl->ring) + LARGE_RING_OFFSET;
 		break;
 	default:
-		ctrl->write.buffer = xc_gntshr_share_pages(ctrl->gntshr, domain,
+		ctrl->write.buffer = xengntshr_share_pages(ctrl->gntshr, domain,
 			pages_right, ctrl->ring->grants + pages_left, 1);
 		if (!ctrl->write.buffer)
 			goto out_unmap_left;
@@ -129,9 +129,9 @@ out:
 	return ring_ref;
 out_unmap_left:
 	if (pages_left)
-		xc_gntshr_munmap(ctrl->gntshr, ctrl->read.buffer, pages_left);
+		xengntshr_munmap(ctrl->gntshr, ctrl->read.buffer, pages_left);
 out_ring:
-	xc_gntshr_munmap(ctrl->gntshr, ring, 1);
+	xengntshr_munmap(ctrl->gntshr, ring, 1);
 	ring_ref = -1;
 	ctrl->ring = NULL;
 	ctrl->write.order = ctrl->read.order = 0;
@@ -143,7 +143,7 @@ static int init_gnt_cli(struct libxenvchan *ctrl, int domain, uint32_t ring_ref)
 	int rv = -1;
 	uint32_t *grants;
 
-	ctrl->ring = xc_gnttab_map_grant_ref_notify(ctrl->gnttab,
+	ctrl->ring = xengnttab_map_grant_ref_notify(ctrl->gnttab,
 		domain, ring_ref, PROT_READ|PROT_WRITE,
 		offsetof(struct vchan_interface, cli_live), ctrl->event_port);
 
@@ -173,7 +173,7 @@ static int init_gnt_cli(struct libxenvchan *ctrl, int domain, uint32_t ring_ref)
 	default:
 		{
 			int pages_left = 1 << (ctrl->write.order - PAGE_SHIFT);
-			ctrl->write.buffer = xc_gnttab_map_domain_grant_refs(ctrl->gnttab,
+			ctrl->write.buffer = xengnttab_map_domain_grant_refs(ctrl->gnttab,
 				pages_left, domain, grants, PROT_READ|PROT_WRITE);
 			if (!ctrl->write.buffer)
 				goto out_unmap_ring;
@@ -191,7 +191,7 @@ static int init_gnt_cli(struct libxenvchan *ctrl, int domain, uint32_t ring_ref)
 	default:
 		{
 			int pages_right = 1 << (ctrl->read.order - PAGE_SHIFT);
-			ctrl->read.buffer = xc_gnttab_map_domain_grant_refs(ctrl->gnttab,
+			ctrl->read.buffer = xengnttab_map_domain_grant_refs(ctrl->gnttab,
 				pages_right, domain, grants, PROT_READ);
 			if (!ctrl->read.buffer)
 				goto out_unmap_left;
@@ -203,10 +203,10 @@ static int init_gnt_cli(struct libxenvchan *ctrl, int domain, uint32_t ring_ref)
 	return rv;
  out_unmap_left:
 	if (ctrl->write.order >= PAGE_SHIFT)
-		xc_gnttab_munmap(ctrl->gnttab, ctrl->write.buffer,
+		xengnttab_munmap(ctrl->gnttab, ctrl->write.buffer,
 		                 1 << (ctrl->write.order - PAGE_SHIFT));
  out_unmap_ring:
-	xc_gnttab_munmap(ctrl->gnttab, ctrl->ring, 1);
+	xengnttab_munmap(ctrl->gnttab, ctrl->ring, 1);
 	ctrl->ring = 0;
 	ctrl->write.order = ctrl->read.order = 0;
 	rv = -1;
@@ -326,7 +326,7 @@ struct libxenvchan *libxenvchan_server_init(xentoollog_logger *logger, int domai
 		ctrl->write.order = LARGE_RING_SHIFT;
 	}
 
-	ctrl->gntshr = xc_gntshr_open(logger, 0);
+	ctrl->gntshr = xengntshr_open(logger, 0);
 	if (!ctrl->gntshr)
 		goto out;
 
@@ -414,7 +414,7 @@ struct libxenvchan *libxenvchan_client_init(xentoollog_logger *logger, int domai
 	if (!ctrl->event_port)
 		goto fail;
 
-	ctrl->gnttab = xc_gnttab_open(logger, 0);
+	ctrl->gnttab = xengnttab_open(logger, 0);
 	if (!ctrl->gnttab)
 		goto fail;
 
diff --git a/tools/libvchan/io.c b/tools/libvchan/io.c
index 4bd15ed..439e2bd 100644
--- a/tools/libvchan/io.c
+++ b/tools/libvchan/io.c
@@ -365,10 +365,10 @@ void libxenvchan_close(struct libxenvchan *ctrl)
 	if (ctrl->ring) {
 		if (ctrl->is_server) {
 			ctrl->ring->srv_live = 0;
-			xc_gntshr_munmap(ctrl->gntshr, ctrl->ring, 1);
+			xengntshr_munmap(ctrl->gntshr, ctrl->ring, 1);
 		} else {
 			ctrl->ring->cli_live = 0;
-			xc_gnttab_munmap(ctrl->gnttab, ctrl->ring, 1);
+			xengnttab_munmap(ctrl->gnttab, ctrl->ring, 1);
 		}
 	}
 	if (ctrl->event) {
@@ -378,10 +378,10 @@ void libxenvchan_close(struct libxenvchan *ctrl)
 	}
 	if (ctrl->is_server) {
 		if (ctrl->gntshr)
-			xc_gntshr_close(ctrl->gntshr);
+			xengntshr_close(ctrl->gntshr);
 	} else {
 		if (ctrl->gnttab)
-			xc_gnttab_close(ctrl->gnttab);
+			xengnttab_close(ctrl->gnttab);
 	}
 	free(ctrl);
 }
diff --git a/tools/libvchan/libxenvchan.h b/tools/libvchan/libxenvchan.h
index 0517dda..950c6e0 100644
--- a/tools/libvchan/libxenvchan.h
+++ b/tools/libvchan/libxenvchan.h
@@ -46,7 +46,7 @@
 #include <xen/io/libxenvchan.h>
 #include <xen/sys/evtchn.h>
 #include <xenevtchn.h>
-#include <xenctrl.h>
+#include <xengnttab.h>
 
 struct libxenvchan_ring {
 	/* Pointer into the shared page. Offsets into buffer. */
@@ -67,8 +67,8 @@ struct libxenvchan_ring {
 struct libxenvchan {
 	/* Mapping handle for shared ring page */
 	union {
-		xc_gntshr *gntshr; /* for server */
-		xc_gnttab *gnttab; /* for client */
+		xengntshr_handle *gntshr; /* for server */
+		xengnttab_handle *gnttab; /* for client */
 	};
 	/* Pointer to shared ring page */
 	struct vchan_interface *ring;
diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile
index 19ad0df..3c939ce 100644
--- a/tools/libxc/Makefile
+++ b/tools/libxc/Makefile
@@ -42,12 +42,13 @@ CTRL_SRCS-y       += xc_resource.c
 CTRL_SRCS-$(CONFIG_X86) += xc_psr.c
 CTRL_SRCS-$(CONFIG_X86) += xc_pagetab.c
 CTRL_SRCS-$(CONFIG_Linux) += xc_linux.c xc_linux_osdep.c
-CTRL_SRCS-$(CONFIG_FreeBSD) += xc_freebsd.c xc_freebsd_osdep.c xc_nognttab.c xc_nogntshr.c
-CTRL_SRCS-$(CONFIG_SunOS) += xc_solaris.c xc_nognttab.c xc_nogntshr.c
-CTRL_SRCS-$(CONFIG_NetBSD) += xc_netbsd.c xc_nognttab.c xc_nogntshr.c
-CTRL_SRCS-$(CONFIG_NetBSDRump) += xc_netbsd.c xc_nognttab.c xc_nogntshr.c
-CTRL_SRCS-$(CONFIG_MiniOS) += xc_minios.c xc_nogntshr.c
+CTRL_SRCS-$(CONFIG_FreeBSD) += xc_freebsd.c xc_freebsd_osdep.c
+CTRL_SRCS-$(CONFIG_SunOS) += xc_solaris.c
+CTRL_SRCS-$(CONFIG_NetBSD) += xc_netbsd.c
+CTRL_SRCS-$(CONFIG_NetBSDRump) += xc_netbsd.c
+CTRL_SRCS-$(CONFIG_MiniOS) += xc_minios.c
 CTRL_SRCS-y       += xc_evtchn_compat.c
+CTRL_SRCS-y       += xc_gnttab_compat.c
 
 GUEST_SRCS-y :=
 GUEST_SRCS-y += xg_private.c xc_suspend.c
@@ -127,6 +128,8 @@ OSDEP_PIC_OBJS := $(patsubst %.c,%.opic,$(OSDEP_SRCS-y))
 $(CTRL_LIB_OBJS) $(GUEST_LIB_OBJS) $(OSDEP_LIB_OBJS) \
 $(CTRL_PIC_OBJS) $(GUEST_PIC_OBJS) $(OSDEP_PIC_OBJS) : CFLAGS += -include $(XEN_ROOT)/tools/config.h
 
+$(CTRL_LIB_OBJS) $(CTRL_PIC_OBJS): CFLAGS += $(CFLAGS_libxengnttab) $(CFLAGS_libxengntshr)
+
 LIB := libxenctrl.a
 ifneq ($(nosharedlibs),y)
 LIB += libxenctrl.so libxenctrl.so.$(MAJOR) libxenctrl.so.$(MAJOR).$(MINOR)
@@ -210,7 +213,7 @@ libxenctrl.so.$(MAJOR): libxenctrl.so.$(MAJOR).$(MINOR)
 	$(SYMLINK_SHLIB) $< $@
 
 libxenctrl.so.$(MAJOR).$(MINOR): $(CTRL_PIC_OBJS)
-	$(CC) $(LDFLAGS) $(PTHREAD_LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenctrl.so.$(MAJOR) $(SHLIB_LDFLAGS) -o $@ $^ $(LDLIBS_libxentoollog) $(LDLIBS_libxenevtchn) $(DLOPEN_LIBS) $(PTHREAD_LIBS) $(APPEND_LDFLAGS)
+	$(CC) $(LDFLAGS) $(PTHREAD_LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenctrl.so.$(MAJOR) $(SHLIB_LDFLAGS) -o $@ $^ $(LDLIBS_libxentoollog) $(LDLIBS_libxenevtchn) $(LDLIBS_libxengnttab) $(LDLIBS_libxengntshr) $(DLOPEN_LIBS) $(PTHREAD_LIBS) $(APPEND_LDFLAGS)
 
 # libxenguest
 
diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h
index e60aa34..9675ebb 100644
--- a/tools/libxc/include/xenctrl.h
+++ b/tools/libxc/include/xenctrl.h
@@ -5,9 +5,6 @@
  *
  * Copyright (c) 2003-2004, K A Fraser.
  *
- * xc_gnttab functions:
- * Copyright (c) 2007-2008, D G Murray <Derek.Murray@cl.cam.ac.uk>
- *
  * This library 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;
@@ -118,8 +115,6 @@
  */
 
 typedef struct xc_interface_core xc_interface;
-typedef struct xengntdev_handle xc_gnttab;
-typedef struct xengntdev_handle xc_gntshr;
 
 enum xc_error_code {
   XC_ERROR_NONE = 0,
@@ -1528,116 +1523,6 @@ int xc_domain_subscribe_for_suspend(
  * These functions sometimes log messages as above, but not always.
  */
 
-/*
- * Note:
- * After fork a child process must not use any opened xc gnttab
- * handle inherited from their parent. They must open a new handle if
- * they want to interact with xc.
- *
- * Return an fd onto the grant table driver.  Logs errors.
- */
-xc_gnttab *xc_gnttab_open(xentoollog_logger *logger,
-			  unsigned open_flags);
-
-/*
- * Close a handle previously allocated with xc_gnttab_open().
- * Never logs errors.
- */
-int xc_gnttab_close(xc_gnttab *xcg);
-
-/*
- * Memory maps a grant reference from one domain to a local address range.
- * Mappings should be unmapped with xc_gnttab_munmap.  Logs errors.
- *
- * @parm xcg a handle on an open grant table interface
- * @parm domid the domain to map memory from
- * @parm ref the grant reference ID to map
- * @parm prot same flag as in mmap()
- */
-void *xc_gnttab_map_grant_ref(xc_gnttab *xcg,
-                              uint32_t domid,
-                              uint32_t ref,
-                              int prot);
-
-/**
- * Memory maps one or more grant references from one or more domains to a
- * contiguous local address range. Mappings should be unmapped with
- * xc_gnttab_munmap.  Logs errors.
- *
- * @parm xcg a handle on an open grant table interface
- * @parm count the number of grant references to be mapped
- * @parm domids an array of @count domain IDs by which the corresponding @refs
- *              were granted
- * @parm refs an array of @count grant references to be mapped
- * @parm prot same flag as in mmap()
- */
-void *xc_gnttab_map_grant_refs(xc_gnttab *xcg,
-                               uint32_t count,
-                               uint32_t *domids,
-                               uint32_t *refs,
-                               int prot);
-
-/**
- * Memory maps one or more grant references from one domain to a
- * contiguous local address range. Mappings should be unmapped with
- * xc_gnttab_munmap.  Logs errors.
- *
- * @parm xcg a handle on an open grant table interface
- * @parm count the number of grant references to be mapped
- * @parm domid the domain to map memory from
- * @parm refs an array of @count grant references to be mapped
- * @parm prot same flag as in mmap()
- */
-void *xc_gnttab_map_domain_grant_refs(xc_gnttab *xcg,
-                                      uint32_t count,
-                                      uint32_t domid,
-                                      uint32_t *refs,
-                                      int prot);
-
-/**
- * Memory maps a grant reference from one domain to a local address range.
- * Mappings should be unmapped with xc_gnttab_munmap. If notify_offset or
- * notify_port are not -1, this version will attempt to set up an unmap
- * notification at the given offset and event channel. When the page is
- * unmapped, the byte at the given offset will be zeroed and a wakeup will be
- * sent to the given event channel.  Logs errors.
- *
- * @parm xcg a handle on an open grant table interface
- * @parm domid the domain to map memory from
- * @parm ref the grant reference ID to map
- * @parm prot same flag as in mmap()
- * @parm notify_offset The byte offset in the page to use for unmap
- *                     notification; -1 for none.
- * @parm notify_port The event channel port to use for unmap notify, or -1
- */
-void *xc_gnttab_map_grant_ref_notify(xc_gnttab *xcg,
-                                     uint32_t domid,
-                                     uint32_t ref,
-                                     int prot,
-                                     uint32_t notify_offset,
-                                     evtchn_port_t notify_port);
-
-/*
- * Unmaps the @count pages starting at @start_address, which were mapped by a
- * call to xc_gnttab_map_grant_ref or xc_gnttab_map_grant_refs. Never logs.
- */
-int xc_gnttab_munmap(xc_gnttab *xcg,
-                     void *start_address,
-                     uint32_t count);
-
-/*
- * Sets the maximum number of grants that may be mapped by the given instance
- * to @count.  Never logs.
- *
- * N.B. This function must be called after opening the handle, and before any
- *      other functions are invoked on it.
- *
- * N.B. When variable-length grants are mapped, fragmentation may be observed,
- *      and it may not be possible to satisfy requests up to the maximum number
- *      of grants.
- */
-int xc_gnttab_set_max_grants(xc_gnttab *xcg,
-			     uint32_t count);
 
 int xc_gnttab_op(xc_interface *xch, int cmd,
                  void * op, int op_size, int count);
@@ -1648,59 +1533,6 @@ grant_entry_v1_t *xc_gnttab_map_table_v1(xc_interface *xch, int domid, int *gnt_
 grant_entry_v2_t *xc_gnttab_map_table_v2(xc_interface *xch, int domid, int *gnt_num);
 /* Sometimes these don't set errno [fixme], and sometimes they don't log. */
 
-/*
- * Return an fd onto the grant sharing driver.  Logs errors.
- *
- * Note:
- * After fork a child process must not use any opened xc gntshr
- * handle inherited from their parent. They must open a new handle if
- * they want to interact with xc.
- *
- */
-xc_gntshr *xc_gntshr_open(xentoollog_logger *logger,
-			  unsigned open_flags);
-
-/*
- * Close a handle previously allocated with xc_gntshr_open().
- * Never logs errors.
- */
-int xc_gntshr_close(xc_gntshr *xcg);
-
-/*
- * Creates and shares pages with another domain.
- * 
- * @parm xcg a handle to an open grant sharing instance
- * @parm domid the domain to share memory with
- * @parm count the number of pages to share
- * @parm refs the grant references of the pages (output)
- * @parm writable true if the other domain can write to the pages
- * @return local mapping of the pages
- */
-void *xc_gntshr_share_pages(xc_gntshr *xcg, uint32_t domid,
-                            int count, uint32_t *refs, int writable);
-
-/*
- * Creates and shares a page with another domain, with unmap notification.
- * 
- * @parm xcg a handle to an open grant sharing instance
- * @parm domid the domain to share memory with
- * @parm refs the grant reference of the pages (output)
- * @parm writable true if the other domain can write to the page
- * @parm notify_offset The byte offset in the page to use for unmap
- *                     notification; -1 for none.
- * @parm notify_port The event channel port to use for unmap notify, or -1
- * @return local mapping of the page
- */
-void *xc_gntshr_share_page_notify(xc_gntshr *xcg, uint32_t domid,
-                                  uint32_t *ref, int writable,
-                                  uint32_t notify_offset,
-                                  evtchn_port_t notify_port);
-/*
- * Unmaps the @count pages starting at @start_address, which were mapped by a
- * call to xc_gntshr_share_*. Never logs.
- */
-int xc_gntshr_munmap(xc_gntshr *xcg, void *start_address, uint32_t count);
-
 int xc_physdev_map_pirq(xc_interface *xch,
                         int domid,
                         int index,
diff --git a/tools/libxc/include/xenctrl_compat.h b/tools/libxc/include/xenctrl_compat.h
index 48daeb2..d99fa11 100644
--- a/tools/libxc/include/xenctrl_compat.h
+++ b/tools/libxc/include/xenctrl_compat.h
@@ -35,6 +35,54 @@ int xc_evtchn_unmask(xc_evtchn *xce, evtchn_port_t port);
 
 #endif /* XC_WANT_COMPAT_EVTCHN_API */
 
+#ifdef XC_WANT_COMPAT_GNTTAB_API
+
+typedef struct xengntdev_handle xc_gnttab;
+
+xc_gnttab *xc_gnttab_open(xentoollog_logger *logger,
+                          unsigned open_flags);
+int xc_gnttab_close(xc_gnttab *xcg);
+void *xc_gnttab_map_grant_ref(xc_gnttab *xcg,
+                              uint32_t domid,
+                              uint32_t ref,
+                              int prot);
+void *xc_gnttab_map_grant_refs(xc_gnttab *xcg,
+                               uint32_t count,
+                               uint32_t *domids,
+                               uint32_t *refs,
+                               int prot);
+void *xc_gnttab_map_domain_grant_refs(xc_gnttab *xcg,
+                                      uint32_t count,
+                                      uint32_t domid,
+                                      uint32_t *refs,
+                                      int prot);
+void *xc_gnttab_map_grant_ref_notify(xc_gnttab *xcg,
+                                     uint32_t domid,
+                                     uint32_t ref,
+                                     int prot,
+                                     uint32_t notify_offset,
+                                     evtchn_port_t notify_port);
+int xc_gnttab_munmap(xc_gnttab *xcg,
+                     void *start_address,
+                     uint32_t count);
+int xc_gnttab_set_max_grants(xc_gnttab *xcg,
+                             uint32_t count);
+
+typedef struct xengntdev_handle xc_gntshr;
+
+xc_gntshr *xc_gntshr_open(xentoollog_logger *logger,
+                          unsigned open_flags);
+int xc_gntshr_close(xc_gntshr *xcg);
+void *xc_gntshr_share_pages(xc_gntshr *xcg, uint32_t domid,
+                            int count, uint32_t *refs, int writable);
+void *xc_gntshr_share_page_notify(xc_gntshr *xcg, uint32_t domid,
+                                  uint32_t *ref, int writable,
+                                  uint32_t notify_offset,
+                                  evtchn_port_t notify_port);
+int xc_gntshr_munmap(xc_gntshr *xcg, void *start_address, uint32_t count);
+
+#endif /* XC_WANT_COMPAT_GNTTAB_API */
+
 #endif
 
 /*
diff --git a/tools/libxc/xc_gnttab.c b/tools/libxc/xc_gnttab.c
index 53cd670..8c7e906 100644
--- a/tools/libxc/xc_gnttab.c
+++ b/tools/libxc/xc_gnttab.c
@@ -144,59 +144,6 @@ grant_entry_v2_t *xc_gnttab_map_table_v2(xc_interface *xch, int domid,
     return _gnttab_map_table(xch, domid, gnt_num);
 }
 
-void *xc_gnttab_map_grant_ref(xc_gnttab *xgt,
-                              uint32_t domid,
-                              uint32_t ref,
-                              int prot)
-{
-    return osdep_gnttab_grant_map(xgt, 1, 0, prot, &domid, &ref, -1, -1);
-}
-
-void *xc_gnttab_map_grant_refs(xc_gnttab *xgt,
-                               uint32_t count,
-                               uint32_t *domids,
-                               uint32_t *refs,
-                               int prot)
-{
-    return osdep_gnttab_grant_map(xgt, count, 0, prot, domids, refs, -1, -1);
-}
-
-void *xc_gnttab_map_domain_grant_refs(xc_gnttab *xgt,
-                                      uint32_t count,
-                                      uint32_t domid,
-                                      uint32_t *refs,
-                                      int prot)
-{
-    return osdep_gnttab_grant_map(xgt, count, XC_GRANT_MAP_SINGLE_DOMAIN,
-                                  prot, &domid, refs, -1, -1);
-}
-
-void *xc_gnttab_map_grant_ref_notify(xc_gnttab *xgt,
-                                     uint32_t domid,
-                                     uint32_t ref,
-                                     int prot,
-                                     uint32_t notify_offset,
-                                     evtchn_port_t notify_port)
-{
-    return osdep_gnttab_grant_map(xgt, 1, 0, prot,  &domid, &ref,
-                                  notify_offset, notify_port);
-}
-
-void *xc_gntshr_share_pages(xc_gntshr *xcg, uint32_t domid,
-                            int count, uint32_t *refs, int writable)
-{
-    return osdep_gntshr_share_pages(xcg, domid, count, refs, writable, -1, -1);
-}
-
-void *xc_gntshr_share_page_notify(xc_gntshr *xcg, uint32_t domid,
-                                  uint32_t *ref, int writable,
-                                  uint32_t notify_offset,
-                                  evtchn_port_t notify_port)
-{
-    return osdep_gntshr_share_pages(xcg, domid, 1, ref, writable,
-                                    notify_offset, notify_port);
-}
-
 /*
  * Local variables:
  * mode: C
diff --git a/tools/libxc/xc_gnttab_compat.c b/tools/libxc/xc_gnttab_compat.c
new file mode 100644
index 0000000..1f496a1
--- /dev/null
+++ b/tools/libxc/xc_gnttab_compat.c
@@ -0,0 +1,111 @@
+/*
+ * Compat shims for use of 3rd party consumers of libxenctrl xc_gnt{tab,shr}
+ * functionality which has been split into separate libraries.
+ */
+
+#include <xengnttab.h>
+
+#define XC_WANT_COMPAT_GNTTAB_API
+#include "xenctrl.h"
+
+xc_gnttab *xc_gnttab_open(xentoollog_logger *logger,
+                          unsigned open_flags)
+{
+    return xengnttab_open(logger, open_flags);
+}
+
+int xc_gnttab_close(xc_gnttab *xcg)
+{
+    return xengnttab_close(xcg);
+}
+
+void *xc_gnttab_map_grant_ref(xc_gnttab *xcg,
+                              uint32_t domid,
+                              uint32_t ref,
+                              int prot)
+{
+    return xengnttab_map_grant_ref(xcg, domid, ref, prot);
+}
+
+void *xc_gnttab_map_grant_refs(xc_gnttab *xcg,
+                               uint32_t count,
+                               uint32_t *domids,
+                               uint32_t *refs,
+                               int prot)
+{
+    return xengnttab_map_grant_refs(xcg, count, domids, refs, prot);
+}
+
+void *xc_gnttab_map_domain_grant_refs(xc_gnttab *xcg,
+                                      uint32_t count,
+                                      uint32_t domid,
+                                      uint32_t *refs,
+                                      int prot)
+{
+    return xengnttab_map_domain_grant_refs(xcg, count, domid, refs, prot);
+}
+
+void *xc_gnttab_map_grant_ref_notify(xc_gnttab *xcg,
+                                     uint32_t domid,
+                                     uint32_t ref,
+                                     int prot,
+                                     uint32_t notify_offset,
+                                     evtchn_port_t notify_port)
+{
+    return xengnttab_map_grant_ref_notify(xcg, domid, ref, prot,
+                                          notify_offset, notify_port);
+}
+
+int xc_gnttab_munmap(xc_gnttab *xcg,
+                     void *start_address,
+                     uint32_t count)
+{
+    return xengnttab_munmap(xcg, start_address, count);
+}
+
+int xc_gnttab_set_max_grants(xc_gnttab *xcg,
+                             uint32_t count)
+{
+    return xengnttab_set_max_grants(xcg, count);
+}
+
+xc_gntshr *xc_gntshr_open(xentoollog_logger *logger,
+                          unsigned open_flags)
+{
+    return xengntshr_open(logger, open_flags);
+}
+
+int xc_gntshr_close(xc_gntshr *xcg)
+{
+    return xengntshr_close(xcg);
+}
+
+void *xc_gntshr_share_pages(xc_gntshr *xcg, uint32_t domid,
+                            int count, uint32_t *refs, int writable)
+{
+    return xengntshr_share_pages(xcg, domid, count, refs, writable);
+}
+
+void *xc_gntshr_share_page_notify(xc_gntshr *xcg, uint32_t domid,
+                                  uint32_t *ref, int writable,
+                                  uint32_t notify_offset,
+                                  evtchn_port_t notify_port)
+{
+    return xengntshr_share_page_notify(xcg, domid, ref, writable,
+                                       notify_offset, notify_port);
+}
+
+int xc_gntshr_munmap(xc_gntshr *xcg, void *start_address, uint32_t count)
+{
+    return xengntshr_munmap(xcg, start_address, count);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxc/xc_linux_osdep.c b/tools/libxc/xc_linux_osdep.c
index f2c7f10..7246b79 100644
--- a/tools/libxc/xc_linux_osdep.c
+++ b/tools/libxc/xc_linux_osdep.c
@@ -32,8 +32,6 @@
 #include <sys/ioctl.h>
 
 #include <xen/memory.h>
-#include <xen/sys/gntdev.h>
-#include <xen/sys/gntalloc.h>
 
 #include "xenctrl.h"
 #include "xenctrlosdep.h"
@@ -42,9 +40,6 @@
 
 #define ROUNDUP(_x,_w) (((unsigned long)(_x)+(1UL<<(_w))-1) & ~((1UL<<(_w))-1))
 
-#define GTERROR(_l, _f...) xtl_log(_l, XTL_ERROR, errno, "gnttab", _f)
-#define GSERROR(_l, _f...) xtl_log(_l, XTL_ERROR, errno, "gntshr", _f)
-
 static xc_osdep_handle linux_privcmd_open(xc_interface *xch)
 {
     int flags, saved_errno;
@@ -456,281 +451,6 @@ static struct xc_osdep_ops linux_privcmd_ops = {
     },
 };
 
-#define DEVXEN "/dev/xen/"
-
-int osdep_gnttab_open(xc_gnttab *xgt)
-{
-    int fd = open(DEVXEN "gntdev", O_RDWR);
-    if ( fd == -1 )
-        return -1;
-    xgt->fd = fd;
-    return 0;
-}
-
-int osdep_gnttab_close(xc_gnttab *xgt)
-{
-    if ( xgt->fd == -1 )
-        return 0;
-
-    return close(xgt->fd);
-}
-
-int xc_gnttab_set_max_grants(xc_gnttab *xgt, uint32_t count)
-{
-    int fd = xgt->fd, rc;
-    struct ioctl_gntdev_set_max_grants max_grants = { .count = count };
-
-    rc = ioctl(fd, IOCTL_GNTDEV_SET_MAX_GRANTS, &max_grants);
-    if (rc) {
-        /*
-         * Newer (e.g. pv-ops) kernels don't implement this IOCTL,
-         * so ignore the resulting specific failure.
-         */
-        if (errno == ENOTTY)
-            rc = 0;
-        else
-            GTERROR(xgt->logger, "ioctl SET_MAX_GRANTS failed");
-    }
-
-    return rc;
-}
-
-void *osdep_gnttab_grant_map(xc_gnttab *xgt,
-                             uint32_t count, int flags, int prot,
-                             uint32_t *domids, uint32_t *refs,
-                             uint32_t notify_offset,
-                             evtchn_port_t notify_port)
-{
-    int fd = xgt->fd;
-    struct ioctl_gntdev_map_grant_ref *map;
-    unsigned int map_size = ROUNDUP((sizeof(*map) + (count - 1) *
-                                    sizeof(struct ioctl_gntdev_map_grant_ref)),
-                                    XC_PAGE_SHIFT);
-    void *addr = NULL;
-    int domids_stride = 1;
-    int i;
-
-    if (flags & XC_GRANT_MAP_SINGLE_DOMAIN)
-        domids_stride = 0;
-
-    if ( map_size <= XC_PAGE_SIZE )
-        map = alloca(sizeof(*map) +
-                     (count - 1) * sizeof(struct ioctl_gntdev_map_grant_ref));
-    else
-    {
-        map = mmap(NULL, map_size, PROT_READ | PROT_WRITE,
-                   MAP_PRIVATE | MAP_ANON | MAP_POPULATE, -1, 0);
-        if ( map == MAP_FAILED )
-        {
-            GTERROR(xgt->logger, "mmap of map failed");
-            return NULL;
-        }
-    }
-
-    for ( i = 0; i < count; i++ )
-    {
-        map->refs[i].domid = domids[i * domids_stride];
-        map->refs[i].ref = refs[i];
-    }
-
-    map->count = count;
-
-    if ( ioctl(fd, IOCTL_GNTDEV_MAP_GRANT_REF, map) ) {
-        GTERROR(xgt->logger, "ioctl MAP_GRANT_REF failed");
-        goto out;
-    }
-
- retry:
-    addr = mmap(NULL, XC_PAGE_SIZE * count, prot, MAP_SHARED, fd,
-                map->index);
-
-    if (addr == MAP_FAILED && errno == EAGAIN)
-    {
-        /*
-         * The grant hypercall can return EAGAIN if the granted page is
-         * swapped out. Since the paging daemon may be in the same domain, the
-         * hypercall cannot block without causing a deadlock.
-         *
-         * Because there are no notificaitons when the page is swapped in, wait
-         * a bit before retrying, and hope that the page will arrive eventually.
-         */
-        usleep(1000);
-        goto retry;
-    }
-
-    if (addr != MAP_FAILED)
-    {
-        int rv = 0;
-        struct ioctl_gntdev_unmap_notify notify;
-        notify.index = map->index;
-        notify.action = 0;
-        if (notify_offset < XC_PAGE_SIZE * count) {
-            notify.index += notify_offset;
-            notify.action |= UNMAP_NOTIFY_CLEAR_BYTE;
-        }
-        if (notify_port != -1) {
-            notify.event_channel_port = notify_port;
-            notify.action |= UNMAP_NOTIFY_SEND_EVENT;
-        }
-        if (notify.action)
-            rv = ioctl(fd, IOCTL_GNTDEV_SET_UNMAP_NOTIFY, &notify);
-        if (rv) {
-            GTERROR(xgt->logger, "ioctl SET_UNMAP_NOTIFY failed");
-            munmap(addr, count * XC_PAGE_SIZE);
-            addr = MAP_FAILED;
-        }
-    }
-
-    if (addr == MAP_FAILED)
-    {
-        int saved_errno = errno;
-        struct ioctl_gntdev_unmap_grant_ref unmap_grant;
-
-        /* Unmap the driver slots used to store the grant information. */
-        GTERROR(xgt->logger, "mmap failed");
-        unmap_grant.index = map->index;
-        unmap_grant.count = count;
-        ioctl(fd, IOCTL_GNTDEV_UNMAP_GRANT_REF, &unmap_grant);
-        errno = saved_errno;
-        addr = NULL;
-    }
-
- out:
-    if ( map_size > XC_PAGE_SIZE )
-        munmap(map, map_size);
-
-    return addr;
-}
-
-int xc_gnttab_munmap(xc_gnttab *xgt, void *start_address, uint32_t count)
-{
-    int fd = xgt->fd;
-    struct ioctl_gntdev_get_offset_for_vaddr get_offset;
-    struct ioctl_gntdev_unmap_grant_ref unmap_grant;
-    int rc;
-
-    if ( start_address == NULL )
-    {
-        errno = EINVAL;
-        return -1;
-    }
-
-    /* First, it is necessary to get the offset which was initially used to
-     * mmap() the pages.
-     */
-    get_offset.vaddr = (unsigned long)start_address;
-    if ( (rc = ioctl(fd, IOCTL_GNTDEV_GET_OFFSET_FOR_VADDR,
-                     &get_offset)) )
-        return rc;
-
-    if ( get_offset.count != count )
-    {
-        errno = EINVAL;
-        return -1;
-    }
-
-    /* Next, unmap the memory. */
-    if ( (rc = munmap(start_address, count * getpagesize())) )
-        return rc;
-
-    /* Finally, unmap the driver slots used to store the grant information. */
-    unmap_grant.index = get_offset.offset;
-    unmap_grant.count = count;
-    if ( (rc = ioctl(fd, IOCTL_GNTDEV_UNMAP_GRANT_REF, &unmap_grant)) )
-        return rc;
-
-    return 0;
-}
-
-int osdep_gntshr_open(xc_gntshr *xgs)
-{
-    int fd = open(DEVXEN "gntalloc", O_RDWR);
-    if ( fd == -1 )
-        return -1;
-    xgs->fd = fd;
-    return 0;
-}
-
-int osdep_gntshr_close(xc_gntshr *xgs)
-{
-    if ( xgs->fd == -1 )
-        return 0;
-
-    return close(xgs->fd);
-}
-
-void *osdep_gntshr_share_pages(xc_gntshr *xgs,
-                               uint32_t domid, int count,
-                               uint32_t *refs, int writable,
-                               uint32_t notify_offset,
-                               evtchn_port_t notify_port)
-{
-    struct ioctl_gntalloc_alloc_gref *gref_info = NULL;
-    struct ioctl_gntalloc_unmap_notify notify;
-    struct ioctl_gntalloc_dealloc_gref gref_drop;
-    int fd = xgs->fd;
-    int err;
-    void *area = NULL;
-    gref_info = malloc(sizeof(*gref_info) + count * sizeof(uint32_t));
-    if (!gref_info)
-        return NULL;
-    gref_info->domid = domid;
-    gref_info->flags = writable ? GNTALLOC_FLAG_WRITABLE : 0;
-    gref_info->count = count;
-
-    err = ioctl(fd, IOCTL_GNTALLOC_ALLOC_GREF, gref_info);
-    if (err) {
-        GSERROR(xgs->logger, "ioctl failed");
-        goto out;
-    }
-
-    area = mmap(NULL, count * XC_PAGE_SIZE, PROT_READ | PROT_WRITE,
-        MAP_SHARED, fd, gref_info->index);
-
-    if (area == MAP_FAILED) {
-        area = NULL;
-        GSERROR(xgs->logger, "mmap failed");
-        goto out_remove_fdmap;
-    }
-
-    notify.index = gref_info->index;
-    notify.action = 0;
-    if (notify_offset < XC_PAGE_SIZE * count) {
-        notify.index += notify_offset;
-        notify.action |= UNMAP_NOTIFY_CLEAR_BYTE;
-    }
-    if (notify_port != -1) {
-        notify.event_channel_port = notify_port;
-        notify.action |= UNMAP_NOTIFY_SEND_EVENT;
-    }
-    if (notify.action)
-        err = ioctl(fd, IOCTL_GNTALLOC_SET_UNMAP_NOTIFY, &notify);
-    if (err) {
-        GSERROR(xgs->logger, "ioctl SET_UNMAP_NOTIFY failed");
-		munmap(area, count * XC_PAGE_SIZE);
-		area = NULL;
-	}
-
-    memcpy(refs, gref_info->gref_ids, count * sizeof(uint32_t));
-
- out_remove_fdmap:
-    /* Removing the mapping from the file descriptor does not cause the pages to
-     * be deallocated until the mapping is removed.
-     */
-    gref_drop.index = gref_info->index;
-    gref_drop.count = count;
-    ioctl(fd, IOCTL_GNTALLOC_DEALLOC_GREF, &gref_drop);
- out:
-    free(gref_info);
-    return area;
-}
-
-int xc_gntshr_munmap(xc_gntshr *xgs,
-                     void *start_address, uint32_t count)
-{
-    return munmap(start_address, count * XC_PAGE_SIZE);
-}
-
 static struct xc_osdep_ops *linux_osdep_init(xc_interface *xch, enum xc_osdep_type type)
 {
     switch ( type )
diff --git a/tools/libxc/xc_minios.c b/tools/libxc/xc_minios.c
index 2cc9ea9..947b19a 100644
--- a/tools/libxc/xc_minios.c
+++ b/tools/libxc/xc_minios.c
@@ -24,8 +24,6 @@
 #include <mini-os/os.h>
 #include <mini-os/mm.h>
 #include <mini-os/lib.h>
-#include <mini-os/gntmap.h>
-#include <sys/mman.h>
 
 #include <xen/memory.h>
 #include <unistd.h>
@@ -39,7 +37,6 @@
 #include "xc_private.h"
 
 void minios_interface_close_fd(int fd);
-void minios_gnttab_close_fd(int fd);
 
 extern void minios_interface_close_fd(int fd);
 
@@ -203,76 +200,6 @@ void *xc_memalign(xc_interface *xch, size_t alignment, size_t size)
     return memalign(alignment, size);
 }
 
-int osdep_gnttab_open(xc_gnttab *xgt)
-{
-    int fd = alloc_fd(FTYPE_GNTMAP);
-    if ( fd == -1 )
-        return -1;
-    gntmap_init(&files[fd].gntmap);
-    xgt->fd = fd;
-    return 0;
-}
-
-int osdep_gnttab_close(xc_gnttab *xgt)
-{
-    if ( xgt->fd == -1 )
-        return 0;
-
-    return close(xgt->fd);
-}
-
-void minios_gnttab_close_fd(int fd)
-{
-    gntmap_fini(&files[fd].gntmap);
-    files[fd].type = FTYPE_NONE;
-}
-
-void *osdep_gnttab_grant_map(xc_gnttab *xgt,
-                             uint32_t count, int flags, int prot,
-                             uint32_t *domids, uint32_t *refs,
-                             uint32_t notify_offset,
-                             evtchn_port_t notify_port)
-{
-    int fd = xgt->fd;
-    int stride = 1;
-    if (flags & XC_GRANT_MAP_SINGLE_DOMAIN)
-        stride = 0;
-    if (notify_offset != -1 || notify_port != -1) {
-        errno = ENOSYS;
-        return NULL;
-    }
-    return gntmap_map_grant_refs(&files[fd].gntmap,
-                                 count, domids, stride,
-                                 refs, prot & PROT_WRITE);
-}
-
-int xc_gnttab_munmap(xc_gnttab *xgt, void *start_address, uint32_t count)
-{
-    int fd = xgt->fd;
-    int ret;
-    ret = gntmap_munmap(&files[fd].gntmap,
-                        (unsigned long) start_address,
-                        count);
-    if (ret < 0) {
-        errno = -ret;
-        return -1;
-    }
-    return ret;
-}
-
-int xc_gnttab_set_max_grants(xc_gnttab *xgt, uint32_t count)
-{
-    int fd = xgt->fd;
-    int ret;
-    ret = gntmap_set_max_grants(&files[fd].gntmap,
-                                count);
-    if (ret < 0) {
-        errno = -ret;
-        return -1;
-    }
-    return ret;
-}
-
 static struct xc_osdep_ops *minios_osdep_init(xc_interface *xch, enum xc_osdep_type type)
 {
     switch ( type )
diff --git a/tools/libxc/xc_nogntshr.c b/tools/libxc/xc_nogntshr.c
deleted file mode 100644
index 6681018..0000000
--- a/tools/libxc/xc_nogntshr.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/******************************************************************************
- *
- * Copyright (c) 2007-2008, D G Murray <Derek.Murray@cl.cam.ac.uk>
- *
- * This library 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 of the License.
- *
- * This library 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 <stdlib.h>
-
-#include "xc_private.h"
-
-int osdep_gntshr_open(xc_gnttab *xgt)
-{
-    return -1;
-}
-
-int osdep_gntshr_close(xc_gnttab *xgt)
-{
-    return 0;
-}
-
-void *osdep_gntshr_share_pages(xc_gntshr *xgs,
-                               uint32_t domid, int count,
-                               uint32_t *refs, int writable,
-                               uint32_t notify_offset,
-                               evtchn_port_t notify_port)
-{
-    abort()
-}
-
-int xc_gntshr_munmap(xc_gntshr *xgs,
-                     void *start_address, uint32_t count)
-{
-    abort();
-}
diff --git a/tools/libxc/xc_nognttab.c b/tools/libxc/xc_nognttab.c
deleted file mode 100644
index 4b4a2ca..0000000
--- a/tools/libxc/xc_nognttab.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/******************************************************************************
- *
- * Copyright (c) 2007-2008, D G Murray <Derek.Murray@cl.cam.ac.uk>
- *
- * This library 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 of the License.
- *
- * This library 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 <stdlib.h>
-
-#include "xc_private.h"
-
-int osdep_gnttab_open(xc_gnttab *xgt)
-{
-    return -1;
-}
-
-int osdep_gnttab_close(xc_gnttab *xgt)
-{
-    return 0;
-}
-
-int xc_gnttab_set_max_grants(xc_gnttab *xgt, uint32_t count)
-{
-    abort();
-}
-
-void *osdep_gnttab_grant_map(xc_gnttab *xgt,
-                             uint32_t count, int flags, int prot,
-                             uint32_t *domids, uint32_t *refs,
-                             uint32_t notify_offset,
-                             evtchn_port_t notify_port)
-{
-    abort();
-}
-
-int xc_gnttab_munmap(xc_gnttab *xgt, void *start_address, uint32_t count)
-{
-    abort();
-}
diff --git a/tools/libxc/xc_private.c b/tools/libxc/xc_private.c
index b2c3c06..e411210 100644
--- a/tools/libxc/xc_private.c
+++ b/tools/libxc/xc_private.c
@@ -250,86 +250,6 @@ int do_xen_hypercall(xc_interface *xch, privcmd_hypercall_t *hypercall)
     return xch->ops->u.privcmd.hypercall(xch, xch->ops_handle, hypercall);
 }
 
-xc_gnttab *xc_gnttab_open(xentoollog_logger *logger, unsigned open_flags)
-{
-    xc_gnttab *xgt = malloc(sizeof(*xgt));
-    int rc;
-
-    if (!xgt) return NULL;
-
-    xgt->fd = -1;
-    xgt->logger = logger;
-    xgt->logger_tofree  = NULL;
-
-    if (!xgt->logger) {
-        xgt->logger = xgt->logger_tofree =
-            (xentoollog_logger*)
-            xtl_createlogger_stdiostream(stderr, XTL_PROGRESS, 0);
-        if (!xgt->logger) goto err;
-    }
-
-    rc = osdep_gnttab_open(xgt);
-    if ( rc  < 0 ) goto err;
-
-    return xgt;
-
-err:
-    osdep_gnttab_close(xgt);
-    xtl_logger_destroy(xgt->logger_tofree);
-    free(xgt);
-    return NULL;
-}
-
-int xc_gnttab_close(xc_gnttab *xgt)
-{
-    int rc;
-
-    rc = osdep_gnttab_close(xgt);
-    xtl_logger_destroy(xgt->logger_tofree);
-    free(xgt);
-    return rc;
-}
-
-xc_gntshr *xc_gntshr_open(xentoollog_logger *logger, unsigned open_flags)
-{
-    xc_gntshr *xgs = malloc(sizeof(*xgs));
-    int rc;
-
-    if (!xgs) return NULL;
-
-    xgs->fd = -1;
-    xgs->logger = logger;
-    xgs->logger_tofree  = NULL;
-
-    if (!xgs->logger) {
-        xgs->logger = xgs->logger_tofree =
-            (xentoollog_logger*)
-            xtl_createlogger_stdiostream(stderr, XTL_PROGRESS, 0);
-        if (!xgs->logger) goto err;
-    }
-
-    rc = osdep_gntshr_open(xgs);
-    if ( rc  < 0 ) goto err;
-
-    return xgs;
-
-err:
-    osdep_gntshr_close(xgs);
-    xtl_logger_destroy(xgs->logger_tofree);
-    free(xgs);
-    return NULL;
-}
-
-int xc_gntshr_close(xc_gntshr *xgs)
-{
-    int rc;
-
-    rc = osdep_gntshr_close(xgs);
-    xtl_logger_destroy(xgs->logger_tofree);
-    free(xgs);
-    return rc;
-}
-
 static pthread_key_t errbuf_pkey;
 static pthread_once_t errbuf_pkey_once = PTHREAD_ONCE_INIT;
 
diff --git a/tools/libxc/xc_private.h b/tools/libxc/xc_private.h
index 81af034..61f2f45 100644
--- a/tools/libxc/xc_private.h
+++ b/tools/libxc/xc_private.h
@@ -124,30 +124,6 @@ struct xc_interface_core {
     xc_osdep_handle  ops_handle; /* opaque data for xc_osdep_ops */
 };
 
-struct xengntdev_handle {
-    xentoollog_logger *logger, *logger_tofree;
-    int fd;
-};
-
-int osdep_gnttab_open(xc_gnttab *xgt);
-int osdep_gnttab_close(xc_gnttab *xgt);
-
-#define XC_GRANT_MAP_SINGLE_DOMAIN 0x1
-void *osdep_gnttab_grant_map(xc_gnttab *xgt,
-                             uint32_t count, int flags, int prot,
-                             uint32_t *domids, uint32_t *refs,
-                             uint32_t notify_offset,
-                             evtchn_port_t notify_port);
-
-int osdep_gntshr_open(xc_gntshr *xgs);
-int osdep_gntshr_close(xc_gntshr *xgs);
-
-void *osdep_gntshr_share_pages(xc_gntshr *xgs,
-                               uint32_t domid, int count,
-                               uint32_t *refs, int writable,
-                               uint32_t notify_offset,
-                               evtchn_port_t notify_port);
-
 void xc_report_error(xc_interface *xch, int code, const char *fmt, ...)
     __attribute__((format(printf,3,4)));
 void xc_reportv(xc_interface *xch, xentoollog_logger *lg, xentoollog_level,
diff --git a/tools/libxenevtchn/minios.c b/tools/libxenevtchn/minios.c
index 1408182..aefaf2c 100644
--- a/tools/libxenevtchn/minios.c
+++ b/tools/libxenevtchn/minios.c
@@ -24,13 +24,12 @@
 #include <mini-os/events.h>
 #include <mini-os/wait.h>
 
-#include <sys/socket.h>
-
 #include <assert.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <stdio.h>
 #include <stdint.h>
+#include <unistd.h>
 #include <inttypes.h>
 #include <malloc.h>
 
@@ -40,8 +39,6 @@ extern void minios_evtchn_close_fd(int fd);
 
 extern struct wait_queue_head event_queue;
 
-//void minios_evtchn_close_fd(int fd);
-
 /* XXX Note: This is not threadsafe */
 static struct evtchn_port_info* port_alloc(int fd) {
     struct evtchn_port_info *port_info;
diff --git a/tools/libxengnttab/Makefile b/tools/libxengnttab/Makefile
new file mode 100644
index 0000000..15bf0fe
--- /dev/null
+++ b/tools/libxengnttab/Makefile
@@ -0,0 +1,69 @@
+XEN_ROOT = $(CURDIR)/../..
+include $(XEN_ROOT)/tools/Rules.mk
+
+MAJOR    = 1
+MINOR    = 0
+SHLIB_LDFLAGS += -Wl,--version-script=libxengnttab.map
+
+CFLAGS   += -Werror -Wmissing-prototypes
+CFLAGS   += -I./include $(CFLAGS_xeninclude)
+CFLAGS   += $(CFLAGS_libxentoollog)
+
+SRCS-GNTTAB            += gnttab_core.c
+SRCS-GNTSHR            += gntshr_core.c
+
+SRCS-$(CONFIG_Linux)   += $(SRCS-GNTTAB) $(SRCS-GNTSHR) linux.c
+SRCS-$(CONFIG_MiniOS)  += $(SRCS-GNTTAB) gntshr_unimp.c  minios.c
+SRCS-$(CONFIG_FreeBSD) += gnttab_unimp.c gntshr_unimp.c
+SRCS-$(CONFIG_SunOS)   += gnttab_unimp.c gntshr_unimp.c
+SRCS-$(CONFIG_NetBSD)  += gnttab_unimp.c gntshr_unimp.c
+
+LIB_OBJS := $(patsubst %.c,%.o,$(SRCS-y))
+PIC_OBJS := $(patsubst %.c,%.opic,$(SRCS-y))
+
+LIB := libxengnttab.a
+ifneq ($(nosharedlibs),y)
+LIB += libxengnttab.so
+endif
+
+.PHONY: all
+all: build
+
+.PHONY: build
+build:
+	$(MAKE) libs
+
+.PHONY: libs
+libs: headers.chk $(LIB)
+
+headers.chk: $(wildcard include/*.h)
+
+libxengnttab.a: $(LIB_OBJS)
+	$(AR) rc $@ $^
+
+libxengnttab.so: libxengnttab.so.$(MAJOR)
+	$(SYMLINK_SHLIB) $< $@
+libxengnttab.so.$(MAJOR): libxengnttab.so.$(MAJOR).$(MINOR)
+	$(SYMLINK_SHLIB) $< $@
+
+libxengnttab.so.$(MAJOR).$(MINOR): $(PIC_OBJS) libxengnttab.map
+	$(CC) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxengnttab.so.$(MAJOR) $(SHLIB_LDFLAGS) -o $@ $(PIC_OBJS) $(LDLIBS_libxentoollog) $(APPEND_LDFLAGS)
+
+.PHONY: install
+install: build
+	$(INSTALL_DIR) $(DESTDIR)$(libdir)
+	$(INSTALL_DIR) $(DESTDIR)$(includedir)
+	$(INSTALL_SHLIB) libxengnttab.so.$(MAJOR).$(MINOR) $(DESTDIR)$(libdir)
+	$(INSTALL_DATA) libxengnttab.a $(DESTDIR)$(libdir)
+	$(SYMLINK_SHLIB) libxengnttab.so.$(MAJOR).$(MINOR) $(DESTDIR)$(libdir)/libxengnttab.so.$(MAJOR)
+	$(SYMLINK_SHLIB) libxengnttab.so.$(MAJOR) $(DESTDIR)$(libdir)/libxengnttab.so
+	$(INSTALL_DATA) include/xengnttab.h $(DESTDIR)$(includedir)
+
+.PHONY: TAGS
+TAGS:
+	etags -t *.c *.h
+
+.PHONY: clean
+clean:
+	rm -rf *.rpm $(LIB) *~ $(DEPS) $(LIB_OBJS) $(PIC_OBJS)
+	rm -f headers.chk
diff --git a/tools/libxengnttab/gntshr_core.c b/tools/libxengnttab/gntshr_core.c
new file mode 100644
index 0000000..3a3da5a
--- /dev/null
+++ b/tools/libxengnttab/gntshr_core.c
@@ -0,0 +1,89 @@
+/******************************************************************************
+ *
+ * Copyright (c) 2007-2008, D G Murray <Derek.Murray@cl.cam.ac.uk>
+ *
+ * This library 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 of the License.
+ *
+ * This library 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.
+ *
+ * Split out from xc_gnttab.c
+ */
+
+#include <stdlib.h>
+
+#include "private.h"
+
+xengntshr_handle *xengntshr_open(xentoollog_logger *logger, unsigned open_flags)
+{
+    xengntshr_handle *xgs = malloc(sizeof(*xgs));
+    int rc;
+
+    if (!xgs) return NULL;
+
+    xgs->fd = -1;
+    xgs->logger = logger;
+    xgs->logger_tofree  = NULL;
+
+    if (!xgs->logger) {
+        xgs->logger = xgs->logger_tofree =
+            (xentoollog_logger*)
+            xtl_createlogger_stdiostream(stderr, XTL_PROGRESS, 0);
+        if (!xgs->logger) goto err;
+    }
+
+    rc = osdep_gntshr_open(xgs);
+    if ( rc  < 0 ) goto err;
+
+    return xgs;
+
+err:
+    osdep_gntshr_close(xgs);
+    xtl_logger_destroy(xgs->logger_tofree);
+    free(xgs);
+    return NULL;
+}
+
+int xengntshr_close(xengntshr_handle *xgs)
+{
+    int rc;
+
+    rc = osdep_gntshr_close(xgs);
+    xtl_logger_destroy(xgs->logger_tofree);
+    free(xgs);
+    return rc;
+}
+void *xengntshr_share_pages(xengntshr_handle *xcg, uint32_t domid,
+                            int count, uint32_t *refs, int writable)
+{
+    return osdep_gntshr_share_pages(xcg, domid, count, refs, writable, -1, -1);
+}
+
+void *xengntshr_share_page_notify(xengntshr_handle *xcg, uint32_t domid,
+                                  uint32_t *ref, int writable,
+                                  uint32_t notify_offset,
+                                  evtchn_port_t notify_port)
+{
+    return osdep_gntshr_share_pages(xcg, domid, 1, ref, writable,
+                                    notify_offset, notify_port);
+}
+
+int xengntshr_munmap(xengntshr_handle *xgs, void *start_address, uint32_t count)
+{
+    return osdep_gntshr_munmap(xgs, start_address, count);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxengnttab/gntshr_unimp.c b/tools/libxengnttab/gntshr_unimp.c
new file mode 100644
index 0000000..c0acc21
--- /dev/null
+++ b/tools/libxengnttab/gntshr_unimp.c
@@ -0,0 +1,59 @@
+/******************************************************************************
+ *
+ * Copyright (c) 2007-2008, D G Murray <Derek.Murray@cl.cam.ac.uk>
+ *
+ * This library 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 of the License.
+ *
+ * This library 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.
+ *
+ * Split out from xc_gnttab.c
+ */
+
+#include <stdlib.h>
+
+#include "private.h"
+
+xengntshr_handle *xengntshr_open(xentoollog_logger *logger, unsigned open_flags)
+{
+    return NULL;
+}
+
+int xengntshr_close(xengntshr_handle *xgs)
+{
+    return 0;
+}
+
+void *xengntshr_share_pages(xengntshr_handle *xcg, uint32_t domid,
+                            int count, uint32_t *refs, int writable)
+{
+    abort();
+}
+
+void *xengntshr_share_page_notify(xengntshr_handle *xcg, uint32_t domid,
+                                  uint32_t *ref, int writable,
+                                  uint32_t notify_offset,
+                                  evtchn_port_t notify_port)
+{
+    abort();
+}
+
+int xengntshr_munmap(xengntshr_handle *xgs, void *start_address, uint32_t count)
+{
+    abort();
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxengnttab/gnttab_core.c b/tools/libxengnttab/gnttab_core.c
new file mode 100644
index 0000000..2b7bdfd
--- /dev/null
+++ b/tools/libxengnttab/gnttab_core.c
@@ -0,0 +1,118 @@
+/******************************************************************************
+ *
+ * Copyright (c) 2007-2008, D G Murray <Derek.Murray@cl.cam.ac.uk>
+ *
+ * This library 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 of the License.
+ *
+ * This library 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.
+ *
+ * Split out from xc_gnttab.c
+ */
+
+#include <stdlib.h>
+
+#include "private.h"
+
+xengnttab_handle *xengnttab_open(xentoollog_logger *logger, unsigned open_flags)
+{
+    xengnttab_handle *xgt = malloc(sizeof(*xgt));
+    int rc;
+
+    if (!xgt) return NULL;
+
+    xgt->fd = -1;
+    xgt->logger = logger;
+    xgt->logger_tofree  = NULL;
+
+    if (!xgt->logger) {
+        xgt->logger = xgt->logger_tofree =
+            (xentoollog_logger*)
+            xtl_createlogger_stdiostream(stderr, XTL_PROGRESS, 0);
+        if (!xgt->logger) goto err;
+    }
+
+    rc = osdep_gnttab_open(xgt);
+    if ( rc  < 0 ) goto err;
+
+    return xgt;
+
+err:
+    osdep_gnttab_close(xgt);
+    xtl_logger_destroy(xgt->logger_tofree);
+    free(xgt);
+    return NULL;
+}
+
+int xengnttab_close(xengnttab_handle *xgt)
+{
+    int rc;
+
+    rc = osdep_gnttab_close(xgt);
+    xtl_logger_destroy(xgt->logger_tofree);
+    free(xgt);
+    return rc;
+}
+
+int xengnttab_set_max_grants(xengnttab_handle *xgt, uint32_t count)
+{
+    return osdep_gnttab_set_max_grants(xgt, count);
+}
+
+void *xengnttab_map_grant_ref(xengnttab_handle *xgt,
+                              uint32_t domid,
+                              uint32_t ref,
+                              int prot)
+{
+    return osdep_gnttab_grant_map(xgt, 1, 0, prot, &domid, &ref, -1, -1);
+}
+
+void *xengnttab_map_grant_refs(xengnttab_handle *xgt,
+                               uint32_t count,
+                               uint32_t *domids,
+                               uint32_t *refs,
+                               int prot)
+{
+    return osdep_gnttab_grant_map(xgt, count, 0, prot, domids, refs, -1, -1);
+}
+
+void *xengnttab_map_domain_grant_refs(xengnttab_handle *xgt,
+                                      uint32_t count,
+                                      uint32_t domid,
+                                      uint32_t *refs,
+                                      int prot)
+{
+    return osdep_gnttab_grant_map(xgt, count, XENGNTTAB_GRANT_MAP_SINGLE_DOMAIN,
+                                  prot, &domid, refs, -1, -1);
+}
+
+void *xengnttab_map_grant_ref_notify(xengnttab_handle *xgt,
+                                     uint32_t domid,
+                                     uint32_t ref,
+                                     int prot,
+                                     uint32_t notify_offset,
+                                     evtchn_port_t notify_port)
+{
+    return osdep_gnttab_grant_map(xgt, 1, 0, prot,  &domid, &ref,
+                                  notify_offset, notify_port);
+}
+
+int xengnttab_munmap(xengnttab_handle *xgt, void *start_address, uint32_t count)
+{
+    return osdep_gnttab_munmap(xgt, start_address, count);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxengnttab/gnttab_unimp.c b/tools/libxengnttab/gnttab_unimp.c
new file mode 100644
index 0000000..ca5618a
--- /dev/null
+++ b/tools/libxengnttab/gnttab_unimp.c
@@ -0,0 +1,86 @@
+/******************************************************************************
+ *
+ * Copyright (c) 2007-2008, D G Murray <Derek.Murray@cl.cam.ac.uk>
+ *
+ * This library 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 of the License.
+ *
+ * This library 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.
+ *
+ * Split out from xc_gnttab.c
+ */
+
+#include <stdlib.h>
+
+#include "private.h"
+
+xengnttab_handle *xengnttab_open(xentoollog_logger *logger, unsigned open_flags)
+{
+    return NULL;
+}
+
+int xengnttab_close(xengnttab_handle *xgt)
+{
+    return 0;
+}
+
+int xengnttab_set_max_grants(xengnttab_handle *xgt, uint32_t count)
+{
+    abort();
+}
+
+void *xengnttab_map_grant_ref(xengnttab_handle *xgt,
+                              uint32_t domid,
+                              uint32_t ref,
+                              int prot)
+{
+    abort();
+}
+
+void *xengnttab_map_grant_refs(xengnttab_handle *xgt,
+                               uint32_t count,
+                               uint32_t *domids,
+                               uint32_t *refs,
+                               int prot)
+{
+    abort();
+}
+
+void *xengnttab_map_domain_grant_refs(xengnttab_handle *xgt,
+                                      uint32_t count,
+                                      uint32_t domid,
+                                      uint32_t *refs,
+                                      int prot)
+{
+    abort();
+}
+
+void *xengnttab_map_grant_ref_notify(xengnttab_handle *xgt,
+                                     uint32_t domid,
+                                     uint32_t ref,
+                                     int prot,
+                                     uint32_t notify_offset,
+                                     evtchn_port_t notify_port)
+{
+    abort();
+}
+
+int xengnttab_munmap(xengnttab_handle *xgt, void *start_address, uint32_t count)
+{
+    abort();
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxengnttab/include/xengnttab.h b/tools/libxengnttab/include/xengnttab.h
new file mode 100644
index 0000000..b333662
--- /dev/null
+++ b/tools/libxengnttab/include/xengnttab.h
@@ -0,0 +1,215 @@
+/*
+ * This library 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 of the License.
+ *
+ * This library 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.
+ *
+ * Split off from:
+ * xenctrl.h
+ *
+ * A library for low-level access to the Xen control interfaces.
+ *
+ * Copyright (c) 2007-2008, D G Murray <Derek.Murray@cl.cam.ac.uk>
+ */
+#ifndef XENGNTTAB_H
+#define XENGNTTAB_H
+
+#include <stdint.h>
+
+#include <xen/grant_table.h>
+#include <xen/event_channel.h>
+
+/* Callers who don't care don't need to #include <xentoollog.h> */
+typedef struct xentoollog_logger xentoollog_logger;
+
+/*
+ * Grant Table Interface (making use of grants from other domains)
+ */
+
+typedef struct xengntdev_handle xengnttab_handle;
+
+/*
+ * Note:
+ * After fork a child process must not use any opened xc gnttab
+ * handle inherited from their parent. They must open a new handle if
+ * they want to interact with xc.
+ *
+ * Return an fd onto the grant table driver.  Logs errors.
+ */
+xengnttab_handle *xengnttab_open(xentoollog_logger *logger, unsigned open_flags);
+
+/*
+ * Close a handle previously allocated with xengnttab_open().
+ * Never logs errors.
+ */
+int xengnttab_close(xengnttab_handle *xgt);
+
+/*
+ * Memory maps a grant reference from one domain to a local address range.
+ * Mappings should be unmapped with xengnttab_munmap.  Logs errors.
+ *
+ * @parm xgt a handle on an open grant table interface
+ * @parm domid the domain to map memory from
+ * @parm ref the grant reference ID to map
+ * @parm prot same flag as in mmap()
+ */
+void *xengnttab_map_grant_ref(xengnttab_handle *xgt,
+                              uint32_t domid,
+                              uint32_t ref,
+                              int prot);
+
+/**
+ * Memory maps one or more grant references from one or more domains to a
+ * contiguous local address range. Mappings should be unmapped with
+ * xengnttab_munmap.  Logs errors.
+ *
+ * @parm xgt a handle on an open grant table interface
+ * @parm count the number of grant references to be mapped
+ * @parm domids an array of @count domain IDs by which the corresponding @refs
+ *              were granted
+ * @parm refs an array of @count grant references to be mapped
+ * @parm prot same flag as in mmap()
+ */
+void *xengnttab_map_grant_refs(xengnttab_handle *xgt,
+                               uint32_t count,
+                               uint32_t *domids,
+                               uint32_t *refs,
+                               int prot);
+
+/**
+ * Memory maps one or more grant references from one domain to a
+ * contiguous local address range. Mappings should be unmapped with
+ * xengnttab_munmap.  Logs errors.
+ *
+ * @parm xgt a handle on an open grant table interface
+ * @parm count the number of grant references to be mapped
+ * @parm domid the domain to map memory from
+ * @parm refs an array of @count grant references to be mapped
+ * @parm prot same flag as in mmap()
+ */
+void *xengnttab_map_domain_grant_refs(xengnttab_handle *xgt,
+                                      uint32_t count,
+                                      uint32_t domid,
+                                      uint32_t *refs,
+                                      int prot);
+
+/**
+ * Memory maps a grant reference from one domain to a local address range.
+ * Mappings should be unmapped with xengnttab_munmap. If notify_offset or
+ * notify_port are not -1, this version will attempt to set up an unmap
+ * notification at the given offset and event channel. When the page is
+ * unmapped, the byte at the given offset will be zeroed and a wakeup will be
+ * sent to the given event channel.  Logs errors.
+ *
+ * @parm xgt a handle on an open grant table interface
+ * @parm domid the domain to map memory from
+ * @parm ref the grant reference ID to map
+ * @parm prot same flag as in mmap()
+ * @parm notify_offset The byte offset in the page to use for unmap
+ *                     notification; -1 for none.
+ * @parm notify_port The event channel port to use for unmap notify, or -1
+ */
+void *xengnttab_map_grant_ref_notify(xengnttab_handle *xgt,
+                                     uint32_t domid,
+                                     uint32_t ref,
+                                     int prot,
+                                     uint32_t notify_offset,
+                                     evtchn_port_t notify_port);
+
+/*
+ * Unmaps the @count pages starting at @start_address, which were mapped by a
+ * call to xengnttab_map_grant_ref or xengnttab_map_grant_refs. Never logs.
+ */
+int xengnttab_munmap(xengnttab_handle *xgt,
+                     void *start_address,
+                     uint32_t count);
+
+/*
+ * Sets the maximum number of grants that may be mapped by the given instance
+ * to @count.  Never logs.
+ *
+ * N.B. This function must be called after opening the handle, and before any
+ *      other functions are invoked on it.
+ *
+ * N.B. When variable-length grants are mapped, fragmentation may be observed,
+ *      and it may not be possible to satisfy requests up to the maximum number
+ *      of grants.
+ */
+int xengnttab_set_max_grants(xengnttab_handle *xgt,
+			     uint32_t count);
+
+/*
+ * Grant Sharing Interface (allocating and granting pages)
+ */
+
+typedef struct xengntdev_handle xengntshr_handle;
+
+/*
+ * Return an fd onto the grant sharing driver.  Logs errors.
+ *
+ * Note:
+ * After fork a child process must not use any opened xc gntshr
+ * handle inherited from their parent. They must open a new handle if
+ * they want to interact with xc.
+ *
+ */
+xengntshr_handle *xengntshr_open(xentoollog_logger *logger,
+			  unsigned open_flags);
+
+/*
+ * Close a handle previously allocated with xengntshr_open().
+ * Never logs errors.
+ */
+int xengntshr_close(xengntshr_handle *xgs);
+
+/*
+ * Creates and shares pages with another domain.
+ *
+ * @parm xgs a handle to an open grant sharing instance
+ * @parm domid the domain to share memory with
+ * @parm count the number of pages to share
+ * @parm refs the grant references of the pages (output)
+ * @parm writable true if the other domain can write to the pages
+ * @return local mapping of the pages
+ */
+void *xengntshr_share_pages(xengntshr_handle *xgs, uint32_t domid,
+                            int count, uint32_t *refs, int writable);
+
+/*
+ * Creates and shares a page with another domain, with unmap notification.
+ *
+ * @parm xgs a handle to an open grant sharing instance
+ * @parm domid the domain to share memory with
+ * @parm refs the grant reference of the pages (output)
+ * @parm writable true if the other domain can write to the page
+ * @parm notify_offset The byte offset in the page to use for unmap
+ *                     notification; -1 for none.
+ * @parm notify_port The event channel port to use for unmap notify, or -1
+ * @return local mapping of the page
+ */
+void *xengntshr_share_page_notify(xengntshr_handle *xgs, uint32_t domid,
+                                  uint32_t *ref, int writable,
+                                  uint32_t notify_offset,
+                                  evtchn_port_t notify_port);
+/*
+ * Unmaps the @count pages starting at @start_address, which were mapped by a
+ * call to xengntshr_share_*. Never logs.
+ */
+int xengntshr_munmap(xengntshr_handle *xgs, void *start_address, uint32_t count);
+
+#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxengnttab/libxengnttab.map b/tools/libxengnttab/libxengnttab.map
new file mode 100644
index 0000000..b46f9aa
--- /dev/null
+++ b/tools/libxengnttab/libxengnttab.map
@@ -0,0 +1,23 @@
+VERS_1.0 {
+	global:
+		xengnttab_open;
+		xengnttab_close;
+
+		xengnttab_set_max_grants;
+
+		xengnttab_map_domain_grant_refs;
+		xengnttab_map_grant_ref;
+		xengnttab_map_grant_ref_notify;
+		xengnttab_map_grant_refs;
+
+		xengnttab_munmap;
+		
+		xengntshr_open;
+		xengntshr_close;
+		
+		xengntshr_share_page_notify;
+		xengntshr_share_pages;
+		
+		xengntshr_munmap;
+	local: *; /* Do not expose anything by default */
+};
diff --git a/tools/libxengnttab/linux.c b/tools/libxengnttab/linux.c
new file mode 100644
index 0000000..ad912a6
--- /dev/null
+++ b/tools/libxengnttab/linux.c
@@ -0,0 +1,326 @@
+/*
+ * Copyright (c) 2007-2008, D G Murray <Derek.Murray@cl.cam.ac.uk>
+ *
+ * This library 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 of the License.
+ *
+ * This library 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.
+ *
+ * Split out from xc_linux_osdep.c
+ */
+
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+
+#include <xen/sys/gntdev.h>
+#include <xen/sys/gntalloc.h>
+
+#include "private.h"
+
+#define DEVXEN "/dev/xen/"
+
+#define ROUNDUP(_x,_w) (((unsigned long)(_x)+(1UL<<(_w))-1) & ~((1UL<<(_w))-1))
+
+#define GTERROR(_l, _f...) xtl_log(_l, XTL_ERROR, errno, "gnttab", _f)
+#define GSERROR(_l, _f...) xtl_log(_l, XTL_ERROR, errno, "gntshr", _f)
+
+#define PAGE_SHIFT           12
+#define PAGE_SIZE            (1UL << PAGE_SHIFT)
+#define PAGE_MASK            (~(PAGE_SIZE-1))
+
+int osdep_gnttab_open(xengnttab_handle *xgt)
+{
+    int fd = open(DEVXEN "gntdev", O_RDWR);
+    if ( fd == -1 )
+        return -1;
+    xgt->fd = fd;
+    return 0;
+}
+
+int osdep_gnttab_close(xengnttab_handle *xgt)
+{
+    if ( xgt->fd == -1 )
+        return 0;
+
+    return close(xgt->fd);
+}
+
+int osdep_gnttab_set_max_grants(xengnttab_handle *xgt, uint32_t count)
+{
+    int fd = xgt->fd, rc;
+    struct ioctl_gntdev_set_max_grants max_grants = { .count = count };
+
+    rc = ioctl(fd, IOCTL_GNTDEV_SET_MAX_GRANTS, &max_grants);
+    if (rc) {
+        /*
+         * Newer (e.g. pv-ops) kernels don't implement this IOCTL,
+         * so ignore the resulting specific failure.
+         */
+        if (errno == ENOTTY)
+            rc = 0;
+        else
+            GTERROR(xgt->logger, "ioctl SET_MAX_GRANTS failed");
+    }
+
+    return rc;
+}
+
+void *osdep_gnttab_grant_map(xengnttab_handle *xgt,
+                             uint32_t count, int flags, int prot,
+                             uint32_t *domids, uint32_t *refs,
+                             uint32_t notify_offset,
+                             evtchn_port_t notify_port)
+{
+    int fd = xgt->fd;
+    struct ioctl_gntdev_map_grant_ref *map;
+    unsigned int map_size = ROUNDUP((sizeof(*map) + (count - 1) *
+                                    sizeof(struct ioctl_gntdev_map_grant_ref)),
+                                    PAGE_SHIFT);
+    void *addr = NULL;
+    int domids_stride = 1;
+    int i;
+
+    if (flags & XENGNTTAB_GRANT_MAP_SINGLE_DOMAIN)
+        domids_stride = 0;
+
+    if ( map_size <= PAGE_SIZE )
+        map = alloca(sizeof(*map) +
+                     (count - 1) * sizeof(struct ioctl_gntdev_map_grant_ref));
+    else
+    {
+        map = mmap(NULL, map_size, PROT_READ | PROT_WRITE,
+                   MAP_PRIVATE | MAP_ANON | MAP_POPULATE, -1, 0);
+        if ( map == MAP_FAILED )
+        {
+            GTERROR(xgt->logger, "mmap of map failed");
+            return NULL;
+        }
+    }
+
+    for ( i = 0; i < count; i++ )
+    {
+        map->refs[i].domid = domids[i * domids_stride];
+        map->refs[i].ref = refs[i];
+    }
+
+    map->count = count;
+
+    if ( ioctl(fd, IOCTL_GNTDEV_MAP_GRANT_REF, map) ) {
+        GTERROR(xgt->logger, "ioctl MAP_GRANT_REF failed");
+        goto out;
+    }
+
+ retry:
+    addr = mmap(NULL, PAGE_SIZE * count, prot, MAP_SHARED, fd,
+                map->index);
+
+    if (addr == MAP_FAILED && errno == EAGAIN)
+    {
+        /*
+         * The grant hypercall can return EAGAIN if the granted page is
+         * swapped out. Since the paging daemon may be in the same domain, the
+         * hypercall cannot block without causing a deadlock.
+         *
+         * Because there are no notificaitons when the page is swapped in, wait
+         * a bit before retrying, and hope that the page will arrive eventually.
+         */
+        usleep(1000);
+        goto retry;
+    }
+
+    if (addr != MAP_FAILED)
+    {
+        int rv = 0;
+        struct ioctl_gntdev_unmap_notify notify;
+        notify.index = map->index;
+        notify.action = 0;
+        if (notify_offset < PAGE_SIZE * count) {
+            notify.index += notify_offset;
+            notify.action |= UNMAP_NOTIFY_CLEAR_BYTE;
+        }
+        if (notify_port != -1) {
+            notify.event_channel_port = notify_port;
+            notify.action |= UNMAP_NOTIFY_SEND_EVENT;
+        }
+        if (notify.action)
+            rv = ioctl(fd, IOCTL_GNTDEV_SET_UNMAP_NOTIFY, &notify);
+        if (rv) {
+            GTERROR(xgt->logger, "ioctl SET_UNMAP_NOTIFY failed");
+            munmap(addr, count * PAGE_SIZE);
+            addr = MAP_FAILED;
+        }
+    }
+
+    if (addr == MAP_FAILED)
+    {
+        int saved_errno = errno;
+        struct ioctl_gntdev_unmap_grant_ref unmap_grant;
+
+        /* Unmap the driver slots used to store the grant information. */
+        GTERROR(xgt->logger, "mmap failed");
+        unmap_grant.index = map->index;
+        unmap_grant.count = count;
+        ioctl(fd, IOCTL_GNTDEV_UNMAP_GRANT_REF, &unmap_grant);
+        errno = saved_errno;
+        addr = NULL;
+    }
+
+ out:
+    if ( map_size > PAGE_SIZE )
+        munmap(map, map_size);
+
+    return addr;
+}
+
+int osdep_gnttab_munmap(xengnttab_handle *xgt,
+                        void *start_address,
+                        uint32_t count)
+{
+    int fd = xgt->fd;
+    struct ioctl_gntdev_get_offset_for_vaddr get_offset;
+    struct ioctl_gntdev_unmap_grant_ref unmap_grant;
+    int rc;
+
+    if ( start_address == NULL )
+    {
+        errno = EINVAL;
+        return -1;
+    }
+
+    /* First, it is necessary to get the offset which was initially used to
+     * mmap() the pages.
+     */
+    get_offset.vaddr = (unsigned long)start_address;
+    if ( (rc = ioctl(fd, IOCTL_GNTDEV_GET_OFFSET_FOR_VADDR,
+                     &get_offset)) )
+        return rc;
+
+    if ( get_offset.count != count )
+    {
+        errno = EINVAL;
+        return -1;
+    }
+
+    /* Next, unmap the memory. */
+    if ( (rc = munmap(start_address, count * getpagesize())) )
+        return rc;
+
+    /* Finally, unmap the driver slots used to store the grant information. */
+    unmap_grant.index = get_offset.offset;
+    unmap_grant.count = count;
+    if ( (rc = ioctl(fd, IOCTL_GNTDEV_UNMAP_GRANT_REF, &unmap_grant)) )
+        return rc;
+
+    return 0;
+}
+
+int osdep_gntshr_open(xengntshr_handle *xgs)
+{
+    int fd = open(DEVXEN "gntalloc", O_RDWR);
+    if ( fd == -1 )
+        return -1;
+    xgs->fd = fd;
+    return 0;
+}
+
+int osdep_gntshr_close(xengntshr_handle *xgs)
+{
+    if ( xgs->fd == -1 )
+        return 0;
+
+    return close(xgs->fd);
+}
+
+void *osdep_gntshr_share_pages(xengntshr_handle *xgs,
+                               uint32_t domid, int count,
+                               uint32_t *refs, int writable,
+                               uint32_t notify_offset,
+                               evtchn_port_t notify_port)
+{
+    struct ioctl_gntalloc_alloc_gref *gref_info = NULL;
+    struct ioctl_gntalloc_unmap_notify notify;
+    struct ioctl_gntalloc_dealloc_gref gref_drop;
+    int fd = xgs->fd;
+    int err;
+    void *area = NULL;
+    gref_info = malloc(sizeof(*gref_info) + count * sizeof(uint32_t));
+    if (!gref_info)
+        return NULL;
+    gref_info->domid = domid;
+    gref_info->flags = writable ? GNTALLOC_FLAG_WRITABLE : 0;
+    gref_info->count = count;
+
+    err = ioctl(fd, IOCTL_GNTALLOC_ALLOC_GREF, gref_info);
+    if (err) {
+        GSERROR(xgs->logger, "ioctl failed");
+        goto out;
+    }
+
+    area = mmap(NULL, count * PAGE_SIZE, PROT_READ | PROT_WRITE,
+        MAP_SHARED, fd, gref_info->index);
+
+    if (area == MAP_FAILED) {
+        area = NULL;
+        GSERROR(xgs->logger, "mmap failed");
+        goto out_remove_fdmap;
+    }
+
+    notify.index = gref_info->index;
+    notify.action = 0;
+    if (notify_offset < PAGE_SIZE * count) {
+        notify.index += notify_offset;
+        notify.action |= UNMAP_NOTIFY_CLEAR_BYTE;
+    }
+    if (notify_port != -1) {
+        notify.event_channel_port = notify_port;
+        notify.action |= UNMAP_NOTIFY_SEND_EVENT;
+    }
+    if (notify.action)
+        err = ioctl(fd, IOCTL_GNTALLOC_SET_UNMAP_NOTIFY, &notify);
+    if (err) {
+        GSERROR(xgs->logger, "ioctl SET_UNMAP_NOTIFY failed");
+		munmap(area, count * PAGE_SIZE);
+		area = NULL;
+	}
+
+    memcpy(refs, gref_info->gref_ids, count * sizeof(uint32_t));
+
+ out_remove_fdmap:
+    /* Removing the mapping from the file descriptor does not cause the pages to
+     * be deallocated until the mapping is removed.
+     */
+    gref_drop.index = gref_info->index;
+    gref_drop.count = count;
+    ioctl(fd, IOCTL_GNTALLOC_DEALLOC_GREF, &gref_drop);
+ out:
+    free(gref_info);
+    return area;
+}
+
+int osdep_gntshr_munmap(xengntshr_handle *xgs,
+                        void *start_address, uint32_t count)
+{
+    return munmap(start_address, count * PAGE_SIZE);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxengnttab/minios.c b/tools/libxengnttab/minios.c
new file mode 100644
index 0000000..b593232
--- /dev/null
+++ b/tools/libxengnttab/minios.c
@@ -0,0 +1,114 @@
+/*
+ *
+ * Copyright 2007-2008 Samuel Thibault <samuel.thibault@eu.citrix.com>.
+ * All rights reserved.
+ * Use is subject to license terms.
+ *
+ * This library 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 of the License.
+ *
+ * This library 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.
+ *
+ * Splitfrom xc_minios.c
+ */
+
+#include <mini-os/types.h>
+#include <mini-os/os.h>
+#include <mini-os/lib.h>
+
+#include <mini-os/gntmap.h>
+#include <sys/mman.h>
+
+#include <errno.h>
+#include <unistd.h>
+
+#include "private.h"
+
+void minios_gnttab_close_fd(int fd);
+
+int osdep_gnttab_open(xengnttab_handle *xgt)
+{
+    int fd = alloc_fd(FTYPE_GNTMAP);
+    if ( fd == -1 )
+        return -1;
+    gntmap_init(&files[fd].gntmap);
+    xgt->fd = fd;
+    return 0;
+}
+
+int osdep_gnttab_close(xengnttab_handle *xgt)
+{
+    if ( xgt->fd == -1 )
+        return 0;
+
+    return close(xgt->fd);
+}
+
+void minios_gnttab_close_fd(int fd)
+{
+    gntmap_fini(&files[fd].gntmap);
+    files[fd].type = FTYPE_NONE;
+}
+
+void *osdep_gnttab_grant_map(xengnttab_handle *xgt,
+                             uint32_t count, int flags, int prot,
+                             uint32_t *domids, uint32_t *refs,
+                             uint32_t notify_offset,
+                             evtchn_port_t notify_port)
+{
+    int fd = xgt->fd;
+    int stride = 1;
+    if (flags & XENGNTTAB_GRANT_MAP_SINGLE_DOMAIN)
+        stride = 0;
+    if (notify_offset != -1 || notify_port != -1) {
+        errno = ENOSYS;
+        return NULL;
+    }
+    return gntmap_map_grant_refs(&files[fd].gntmap,
+                                 count, domids, stride,
+                                 refs, prot & PROT_WRITE);
+}
+
+int osdep_gnttab_munmap(xengnttab_handle *xgt,
+                        void *start_address,
+                        uint32_t count)
+{
+    int fd = xgt->fd;
+    int ret;
+    ret = gntmap_munmap(&files[fd].gntmap,
+                        (unsigned long) start_address,
+                        count);
+    if (ret < 0) {
+        errno = -ret;
+        return -1;
+    }
+    return ret;
+}
+
+int osdep_gnttab_set_max_grants(xengnttab_handle *xgt, uint32_t count)
+{
+    int fd = xgt->fd;
+    int ret;
+    ret = gntmap_set_max_grants(&files[fd].gntmap,
+                                count);
+    if (ret < 0) {
+        errno = -ret;
+        return -1;
+    }
+    return ret;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxengnttab/private.h b/tools/libxengnttab/private.h
new file mode 100644
index 0000000..cb7e2cc
--- /dev/null
+++ b/tools/libxengnttab/private.h
@@ -0,0 +1,47 @@
+#ifndef XENGNTTAB_PRIVATE_H
+#define XENGNTTAB_PRIVATE_H
+
+#include <xentoollog.h>
+#include <xengnttab.h>
+
+struct xengntdev_handle {
+    xentoollog_logger *logger, *logger_tofree;
+    int fd;
+};
+
+int osdep_gnttab_open(xengnttab_handle *xgt);
+int osdep_gnttab_close(xengnttab_handle *xgt);
+
+int osdep_gnttab_set_max_grants(xengnttab_handle *xgt, uint32_t count);
+
+#define XENGNTTAB_GRANT_MAP_SINGLE_DOMAIN 0x1
+void *osdep_gnttab_grant_map(xengnttab_handle *xgt,
+                             uint32_t count, int flags, int prot,
+                             uint32_t *domids, uint32_t *refs,
+                             uint32_t notify_offset,
+                             evtchn_port_t notify_port);
+int osdep_gnttab_munmap(xengnttab_handle *xgt,
+                        void *start_address,
+                        uint32_t count);
+int osdep_gntshr_open(xengntshr_handle *xgs);
+int osdep_gntshr_close(xengntshr_handle *xgs);
+
+void *osdep_gntshr_share_pages(xengntshr_handle *xgs,
+                               uint32_t domid, int count,
+                               uint32_t *refs, int writable,
+                               uint32_t notify_offset,
+                               evtchn_port_t notify_port);
+int osdep_gntshr_munmap(xengntshr_handle *xgs,
+                        void *start_address, uint32_t count);
+
+#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/xenstore/Makefile b/tools/xenstore/Makefile
index c161046..178771f 100644
--- a/tools/xenstore/Makefile
+++ b/tools/xenstore/Makefile
@@ -78,8 +78,10 @@ init-xenstore-domain.o: CFLAGS += $(CFLAGS_libxenguest)
 init-xenstore-domain: init-xenstore-domain.o $(LIBXENSTORE)
 	$(CC) $^ $(LDFLAGS) $(LDLIBS_libxenevtchn) $(LDLIBS_libxenctrl) $(LDLIBS_libxenguest) $(LDLIBS_libxenstore) -o $@ $(APPEND_LDFLAGS)
 
+$(XENSTORED_OBJS): CFLAGS += $(CFLAGS_libxengnttab)
+
 xenstored: $(XENSTORED_OBJS)
-	$(CC) $^ $(LDFLAGS) $(LDLIBS_libxenevtchn) $(LDLIBS_libxenctrl) $(SOCKET_LIBS) -o $@ $(APPEND_LDFLAGS)
+	$(CC) $^ $(LDFLAGS) $(LDLIBS_libxenevtchn) $(LDLIBS_libxengnttab) $(LDLIBS_libxenctrl) $(SOCKET_LIBS) -o $@ $(APPEND_LDFLAGS)
 
 xenstored.a: $(XENSTORED_OBJS)
 	$(AR) cr $@ $^
diff --git a/tools/xenstore/xenstored_core.h b/tools/xenstore/xenstored_core.h
index dcf95b5..2b01076 100644
--- a/tools/xenstore/xenstored_core.h
+++ b/tools/xenstore/xenstored_core.h
@@ -21,12 +21,14 @@
 #define _XENSTORED_CORE_H
 
 #include <xenctrl.h>
+#include <xengnttab.h>
 
 #include <sys/types.h>
 #include <dirent.h>
 #include <stdbool.h>
 #include <stdint.h>
 #include <errno.h>
+
 #include "xenstore_lib.h"
 #include "list.h"
 #include "tdb.h"
@@ -197,7 +199,7 @@ void finish_daemonize(void);
 /* Open a pipe for signal handling */
 void init_pipe(int reopen_log_pipe[2]);
 
-xc_gnttab **xcg_handle;
+xengnttab_handle **xgt_handle;
 
 #endif /* _XENSTORED_CORE_H */
 
diff --git a/tools/xenstore/xenstored_domain.c b/tools/xenstore/xenstored_domain.c
index b649107..aa4d896 100644
--- a/tools/xenstore/xenstored_domain.c
+++ b/tools/xenstore/xenstored_domain.c
@@ -35,7 +35,7 @@
 #include <xen/grant_table.h>
 
 static xc_interface **xc_handle;
-xc_gnttab **xcg_handle;
+xengnttab_handle **xgt_handle;
 static evtchn_port_t virq_port;
 
 xenevtchn_handle *xce_handle = NULL;
@@ -167,9 +167,9 @@ static int readchn(struct connection *conn, void *data, unsigned int len)
 
 static void *map_interface(domid_t domid, unsigned long mfn)
 {
-	if (*xcg_handle != NULL) {
+	if (*xgt_handle != NULL) {
 		/* this is the preferred method */
-		return xc_gnttab_map_grant_ref(*xcg_handle, domid,
+		return xengnttab_map_grant_ref(*xgt_handle, domid,
 			GNTTAB_RESERVED_XENSTORE, PROT_READ|PROT_WRITE);
 	} else {
 		return xc_map_foreign_range(*xc_handle, domid,
@@ -179,8 +179,8 @@ static void *map_interface(domid_t domid, unsigned long mfn)
 
 static void unmap_interface(void *interface)
 {
-	if (*xcg_handle != NULL)
-		xc_gnttab_munmap(*xcg_handle, interface, 1);
+	if (*xgt_handle != NULL)
+		xengnttab_munmap(*xgt_handle, interface, 1);
 	else
 		munmap(interface, XC_PAGE_SIZE);
 }
@@ -578,9 +578,9 @@ static int close_xc_handle(void *_handle)
 	return 0;
 }
 
-static int close_xcg_handle(void *_handle)
+static int close_xgt_handle(void *_handle)
 {
-	xc_gnttab_close(*(xc_gnttab **)_handle);
+	xengnttab_close(*(xengnttab_handle **)_handle);
 	return 0;
 }
 
@@ -635,15 +635,15 @@ void domain_init(void)
 
 	talloc_set_destructor(xc_handle, close_xc_handle);
 
-	xcg_handle = talloc(talloc_autofree_context(), xc_gnttab*);
-	if (!xcg_handle)
+	xgt_handle = talloc(talloc_autofree_context(), xengnttab_handle*);
+	if (!xgt_handle)
 		barf_perror("Failed to allocate domain gnttab handle");
 
-	*xcg_handle = xc_gnttab_open(NULL, 0);
-	if (*xcg_handle == NULL)
+	*xgt_handle = xengnttab_open(NULL, 0);
+	if (*xgt_handle == NULL)
 		xprintf("WARNING: Failed to open connection to gnttab\n");
 	else
-		talloc_set_destructor(xcg_handle, close_xcg_handle);
+		talloc_set_destructor(xgt_handle, close_xgt_handle);
 
 	xce_handle = xenevtchn_open(NULL, 0);
 
diff --git a/tools/xenstore/xenstored_minios.c b/tools/xenstore/xenstored_minios.c
index f9c921e..f929e31 100644
--- a/tools/xenstore/xenstored_minios.c
+++ b/tools/xenstore/xenstored_minios.c
@@ -18,7 +18,6 @@
 */
 #include <sys/types.h>
 #include <sys/mman.h>
-#include <xenctrl.h>
 #include "xenstored_core.h"
 #include <xen/grant_table.h>
 
@@ -51,12 +50,12 @@ evtchn_port_t xenbus_evtchn(void)
 
 void *xenbus_map(void)
 {
-	return xc_gnttab_map_grant_ref(*xcg_handle, xenbus_master_domid(),
+	return xengnttab_map_grant_ref(*xgt_handle, xenbus_master_domid(),
 			GNTTAB_RESERVED_XENSTORE, PROT_READ|PROT_WRITE);
 }
 
 void unmap_xenbus(void *interface)
 {
-	xc_gnttab_munmap(*xcg_handle, interface, 1);
+	xengnttab_munmap(*xgt_handle, interface, 1);
 }
 
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH XEN v2 09/15] tools/libxc: Remove osdep indirection for privcmd
  2015-07-15 15:46 [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries Ian Campbell
                   ` (7 preceding siblings ...)
  2015-07-15 15:46 ` [PATCH XEN v2 08/15] tools: Refactor /dev/xen/gnt{dev, shr} wrappers into libxengnttab Ian Campbell
@ 2015-07-15 15:46 ` Ian Campbell
       [not found]   ` <01C96D24-A13F-46A6-A8A9-5C04E2E199AF@citrix.com>
  2015-07-15 15:46 ` [PATCH XEN v2 10/15] tools: Refactor hypercall calling wrappers into libxencall Ian Campbell
                   ` (18 subsequent siblings)
  27 siblings, 1 reply; 55+ messages in thread
From: Ian Campbell @ 2015-07-15 15:46 UTC (permalink / raw)
  To: ian.jackson, wei.liu2, xen-devel
  Cc: roger.pau, David Scott, Ian Campbell, stefano.stabellini

The alternative backend (a xen-api/xapi shim) is no longer around and
so this stuff is now just baggage which is getting in the way of
refactoring libxenctrl.

Nested virt probably suffices for this use case now.

This was the last component of the osdep infrastructure, so all the
dynamic loading etc stuff all falls away too.

As part of this I was forced to investigate the twisty
xc_map_foreign_* maze, which I have added to the
toolstack-library-apis doc in the hopes of doing something sensible.

NetBSD and Solaris now call xc_map_foreign_bulk_compat directly from
their xc_map_foreign_bulk, which could have been achieved by using
some ifdefs around a renamed function. This will fall out in the wash
when these functions move to their own library.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
Cc: David Scott <david.scott@citrix.com>
---
 config/FreeBSD.mk                       |   2 -
 config/NetBSD.mk                        |   3 -
 config/NetBSDRump.mk                    |   1 -
 config/StdGNU.mk                        |   1 -
 config/SunOS.mk                         |   1 -
 docs/misc/toolstack-library-abis.pandoc |  64 +++++++++++-
 tools/libxc/Makefile                    |  27 ++---
 tools/libxc/include/xenctrl.h           |   9 --
 tools/libxc/include/xenctrlosdep.h      | 134 ------------------------
 tools/libxc/xc_foreign_memory.c         |  31 +-----
 tools/libxc/xc_freebsd_osdep.c          | 100 +++++-------------
 tools/libxc/xc_hcall_buf.c              |   6 +-
 tools/libxc/xc_linux_osdep.c            |  88 +++++-----------
 tools/libxc/xc_minios.c                 |  82 +++++----------
 tools/libxc/xc_netbsd.c                 |  90 ++++++-----------
 tools/libxc/xc_private.c                | 174 ++------------------------------
 tools/libxc/xc_private.h                |  19 ++--
 tools/libxc/xc_solaris.c                |  90 ++++++-----------
 tools/libxc/xenctrl_osdep_ENOSYS.c      | 123 ----------------------
 tools/ocaml/libs/xc/xenctrl.ml          |   2 -
 tools/ocaml/libs/xc/xenctrl.mli         |   1 -
 tools/ocaml/libs/xc/xenctrl_stubs.c     |   7 --
 tools/ocaml/xenstored/domains.ml        |   6 +-
 tools/ocaml/xenstored/xenstored.ml      |   5 +-
 24 files changed, 240 insertions(+), 826 deletions(-)
 delete mode 100644 tools/libxc/include/xenctrlosdep.h
 delete mode 100644 tools/libxc/xenctrl_osdep_ENOSYS.c

diff --git a/config/FreeBSD.mk b/config/FreeBSD.mk
index 5a13d607..bb3a5d0 100644
--- a/config/FreeBSD.mk
+++ b/config/FreeBSD.mk
@@ -1,6 +1,4 @@
 include $(XEN_ROOT)/config/StdGNU.mk
 
-DLOPEN_LIBS =
-
 # No wget on FreeBSD base system
 WGET = ftp
diff --git a/config/NetBSD.mk b/config/NetBSD.mk
index 21318d6..cf766e5 100644
--- a/config/NetBSD.mk
+++ b/config/NetBSD.mk
@@ -1,6 +1,3 @@
 include $(XEN_ROOT)/config/StdGNU.mk
 
-# Override settings for this OS
-DLOPEN_LIBS =
-
 WGET = ftp
diff --git a/config/NetBSDRump.mk b/config/NetBSDRump.mk
index 2a87218..74755a1 100644
--- a/config/NetBSDRump.mk
+++ b/config/NetBSDRump.mk
@@ -1,6 +1,5 @@
 include $(XEN_ROOT)/config/StdGNU.mk
 
-DLOPEN_LIBS =
 PTHREAD_LIBS =
 
 WGET = ftp
diff --git a/config/StdGNU.mk b/config/StdGNU.mk
index 129d5c8..39d36b2 100644
--- a/config/StdGNU.mk
+++ b/config/StdGNU.mk
@@ -31,7 +31,6 @@ DEBUG_DIR ?= /usr/lib/debug
 
 SOCKET_LIBS =
 UTIL_LIBS = -lutil
-DLOPEN_LIBS = -ldl
 
 SONAME_LDFLAG = -soname
 SHLIB_LDFLAGS = -shared
diff --git a/config/SunOS.mk b/config/SunOS.mk
index db5e898..86a384d 100644
--- a/config/SunOS.mk
+++ b/config/SunOS.mk
@@ -27,7 +27,6 @@ SunOS_LIBDIR_x86_64 = /usr/sfw/lib/amd64
 SOCKET_LIBS = -lsocket
 PTHREAD_LIBS = -lpthread
 UTIL_LIBS =
-DLOPEN_LIBS = -ldl
 
 SONAME_LDFLAG = -h
 SHLIB_LDFLAGS = -R $(SunOS_LIBDIR) -shared
diff --git a/docs/misc/toolstack-library-abis.pandoc b/docs/misc/toolstack-library-abis.pandoc
index 6b6146a..d1550a6 100644
--- a/docs/misc/toolstack-library-abis.pandoc
+++ b/docs/misc/toolstack-library-abis.pandoc
@@ -187,7 +187,6 @@ Notes:
 ### Basic interface
 
     - xc_interface_close
-    - xc_interface_is_fake
     - xc_interface_open
 
 ### Event channels
@@ -511,7 +510,6 @@ Symbols:
     - xc_monitor_write_ctrlreg
     - xc_nodemap_alloc
     - xc_numainfo
-    - xc_osdep_log
     - xc_pcitopoinfo
     - xc_perfc_query
     - xc_perfc_query_number
@@ -871,3 +869,65 @@ functionality areas:
     - xc_kexec_load
     - xc_kexec_unload
     - xc_version
+
+# Foreign memory mapping functions
+
+The `xc_map_foreign_*` functions are a bit of a twisty maze.
+
+osdep level interfaces:
+
+Interface            Linux Minios Netbsd Freebsd Solaris
+-------------------- ----- ------ ------ ------- -------
+`map_foreign_batch`  Y     Y      Y              Y
+`map_foreign_bulk`   Y     Y      compat Y       compat
+`map_foreign_range`  Y     Y      Y      Y       Y
+`map_foreign_ranges` Y     Y      Y      Y       Y
+
+_compat_ means using `xc_map_foreign_bulk_compat`
+
+`xc_map_foreign_pages` is common and implemented using
+`xc_map_foreign_bulk`.
+
+Some osdep call other `xc_map_foreign_*` recursivley:
+
+Interface            Linux                        FreeBSD
+-------------------- ---------------------------- -------------------------
+`map_foreign_batch`  `IOCTL_PRIVCMD_MMAPBATCH`    N/A
+`map_foreign_bulk`   `IOCTL_PRIVCMD_MMAPBATCH_V2` `IOCTL_PRIVCMD_MMAPBATCH`
+`map_foreign_range`  `xc_map_foreign_pages`       `xc_map_foreign_pages`
+`map_foreign_ranges` `xc_map_foreign_pages`       `xc_map_foreign_pages`
+
+libxenctrl level interfaces:
+
+Interface               Underlying interface
+----------------------  ---------------------------
+`xc_map_foreign_pages`  `xc_map_foreign_bulk`
+`xc_map_foreign_range`  `osdep: map_foreign_range`
+`xc_map_foreign_ranges` `osdep: map_foreign_ranges`
+`xc_map_foreign_batch`  `osdep: map_foreign_batch`
+`xc_map_foreign_bulk`   `osdep: map_foreign_bulk`
+
+`osdep: *` have been collapsed since osdep layer was removed.
+
+`xc_map_foreign_bulk_compat` is an internal helper used by osdep
+backends which have not implemented there own version. It uses
+`xc_map_foreign_batch`.
+
+`xc_map_foreign_batch_single` is part of linux osdep, but name has
+leaked.
+
+Interface               Internal users               External users
+----------------------  --------------               --------------
+`xc_map_foreign_pages`  xenpaging                    qemu-pv
+`xc_map_foreign_range`  xenconsole, kdd, libxl,      qemu-dm, qemu-pv
+                        mfndump, memshrtool, xenmon,
+                        xenstored, xentrace
+`xc_map_foreign_ranges` NONE
+`xc_map_foreign_batch`  xenmon, xenpaging, xentrace
+`xc_map_foreign_bulk`   used recursively             qemu-dm
+
+Only one interface should become a stable API. Something based on
+`xc_map_foreign_bulk` seems most appropriate (it is used by
+`xc_map_foreign_pages` as well as by xc_map_foreign_range` and
+`xc_map_foreign_ranges` on Linux + FreeBSD. A compat version exists in
+terms for `xc_map_foreign_batch` for other OSes.
diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile
index 3c939ce..77d2ae1 100644
--- a/tools/libxc/Makefile
+++ b/tools/libxc/Makefile
@@ -102,8 +102,6 @@ GUEST_SRCS-y                 += xc_dom_decompress_unsafe_lzo1x.c
 GUEST_SRCS-y                 += xc_dom_decompress_unsafe_xz.c
 endif
 
-OSDEP_SRCS-y                 += xenctrl_osdep_ENOSYS.c
-
 -include $(XEN_TARGET_ARCH)/Makefile
 
 CFLAGS   += -Werror -Wmissing-prototypes
@@ -122,11 +120,8 @@ CTRL_PIC_OBJS := $(patsubst %.c,%.opic,$(CTRL_SRCS-y))
 GUEST_LIB_OBJS := $(patsubst %.c,%.o,$(GUEST_SRCS-y))
 GUEST_PIC_OBJS := $(patsubst %.c,%.opic,$(GUEST_SRCS-y))
 
-OSDEP_LIB_OBJS := $(patsubst %.c,%.o,$(OSDEP_SRCS-y))
-OSDEP_PIC_OBJS := $(patsubst %.c,%.opic,$(OSDEP_SRCS-y))
-
-$(CTRL_LIB_OBJS) $(GUEST_LIB_OBJS) $(OSDEP_LIB_OBJS) \
-$(CTRL_PIC_OBJS) $(GUEST_PIC_OBJS) $(OSDEP_PIC_OBJS) : CFLAGS += -include $(XEN_ROOT)/tools/config.h
+$(CTRL_LIB_OBJS) $(GUEST_LIB_OBJS) \
+$(CTRL_PIC_OBJS) $(GUEST_PIC_OBJS): CFLAGS += -include $(XEN_ROOT)/tools/config.h
 
 $(CTRL_LIB_OBJS) $(CTRL_PIC_OBJS): CFLAGS += $(CFLAGS_libxengnttab) $(CFLAGS_libxengntshr)
 
@@ -140,17 +135,13 @@ ifneq ($(nosharedlibs),y)
 LIB += libxenguest.so libxenguest.so.$(MAJOR) libxenguest.so.$(MAJOR).$(MINOR)
 endif
 
-ifneq ($(nosharedlibs),y)
-LIB += xenctrl_osdep_ENOSYS.so
-endif
-
 genpath-target = $(call buildmakevars2header,_paths.h)
 $(eval $(genpath-target))
 
 xc_private.h: _paths.h
 
-$(CTRL_LIB_OBJS) $(GUEST_LIB_OBJS) $(OSDEP_LIB_OBJS) \
-$(CTRL_PIC_OBJS) $(GUEST_PIC_OBJS) $(OSDEP_PIC_OBJS): xc_private.h
+$(CTRL_LIB_OBJS) $(GUEST_LIB_OBJS) \
+$(CTRL_PIC_OBJS) $(GUEST_PIC_OBJS): xc_private.h
 
 .PHONY: all
 all: build
@@ -170,7 +161,7 @@ install: build
 	$(INSTALL_DATA) libxenctrl.a $(DESTDIR)$(libdir)
 	$(SYMLINK_SHLIB) libxenctrl.so.$(MAJOR).$(MINOR) $(DESTDIR)$(libdir)/libxenctrl.so.$(MAJOR)
 	$(SYMLINK_SHLIB) libxenctrl.so.$(MAJOR) $(DESTDIR)$(libdir)/libxenctrl.so
-	$(INSTALL_DATA) include/xenctrl.h include/xenctrl_compat.h include/xenctrlosdep.h $(DESTDIR)$(includedir)
+	$(INSTALL_DATA) include/xenctrl.h include/xenctrl_compat.h $(DESTDIR)$(includedir)
 	$(INSTALL_SHLIB) libxenguest.so.$(MAJOR).$(MINOR) $(DESTDIR)$(libdir)
 	$(INSTALL_DATA) libxenguest.a $(DESTDIR)$(libdir)
 	$(SYMLINK_SHLIB) libxenguest.so.$(MAJOR).$(MINOR) $(DESTDIR)$(libdir)/libxenguest.so.$(MAJOR)
@@ -186,8 +177,7 @@ clean:
 	rm -rf *.rpm $(LIB) *~ $(DEPS) \
             _paths.h \
             $(CTRL_LIB_OBJS) $(CTRL_PIC_OBJS) \
-            $(GUEST_LIB_OBJS) $(GUEST_PIC_OBJS) \
-            $(OSDEP_LIB_OBJS) $(OSDEP_PIC_OBJS)
+            $(GUEST_LIB_OBJS) $(GUEST_PIC_OBJS)
 
 .PHONY: distclean
 distclean: clean
@@ -213,7 +203,7 @@ libxenctrl.so.$(MAJOR): libxenctrl.so.$(MAJOR).$(MINOR)
 	$(SYMLINK_SHLIB) $< $@
 
 libxenctrl.so.$(MAJOR).$(MINOR): $(CTRL_PIC_OBJS)
-	$(CC) $(LDFLAGS) $(PTHREAD_LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenctrl.so.$(MAJOR) $(SHLIB_LDFLAGS) -o $@ $^ $(LDLIBS_libxentoollog) $(LDLIBS_libxenevtchn) $(LDLIBS_libxengnttab) $(LDLIBS_libxengntshr) $(DLOPEN_LIBS) $(PTHREAD_LIBS) $(APPEND_LDFLAGS)
+	$(CC) $(LDFLAGS) $(PTHREAD_LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenctrl.so.$(MAJOR) $(SHLIB_LDFLAGS) -o $@ $^ $(LDLIBS_libxentoollog) $(LDLIBS_libxenevtchn) $(LDLIBS_libxengnttab) $(LDLIBS_libxengntshr) $(PTHREAD_LIBS) $(APPEND_LDFLAGS)
 
 # libxenguest
 
@@ -238,8 +228,5 @@ libxenguest.so.$(MAJOR).$(MINOR): COMPRESSION_LIBS = $(call zlib-options,l)
 libxenguest.so.$(MAJOR).$(MINOR): $(GUEST_PIC_OBJS) libxenctrl.so
 	$(CC) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenguest.so.$(MAJOR) $(SHLIB_LDFLAGS) -o $@ $(GUEST_PIC_OBJS) $(COMPRESSION_LIBS) -lz $(LDLIBS_libxenevtchn) $(LDLIBS_libxenctrl) $(PTHREAD_LIBS) $(APPEND_LDFLAGS)
 
-xenctrl_osdep_ENOSYS.so: $(OSDEP_PIC_OBJS) libxenctrl.so
-	$(CC) $(LDFLAGS) $(SHLIB_LDFLAGS) -o $@ $(OSDEP_PIC_OBJS) $(LDLIBS_libxenctrl) $(APPEND_LDFLAGS)
-
 -include $(DEPS)
 
diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h
index 9675ebb..61f68bb 100644
--- a/tools/libxc/include/xenctrl.h
+++ b/tools/libxc/include/xenctrl.h
@@ -182,15 +182,6 @@ enum xc_open_flags {
  */
 int xc_interface_close(xc_interface *xch);
 
-/**
- * Query the active OS interface (i.e. that which would be returned by
- * xc_interface_open) to find out if it is fake (i.e. backends onto
- * something other than an actual Xen hypervisor).
- *
- * @return 0 is "real", >0 if fake, -1 on error.
- */
-int xc_interface_is_fake(void);
-
 /*
  * HYPERCALL SAFE MEMORY BUFFER
  *
diff --git a/tools/libxc/include/xenctrlosdep.h b/tools/libxc/include/xenctrlosdep.h
deleted file mode 100644
index bad10f6..0000000
--- a/tools/libxc/include/xenctrlosdep.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/******************************************************************************
- *
- * Interface to OS specific low-level operations
- *
- * Copyright (c) 2010, Citrix Systems Inc.
- *
- * This library 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 of the License.
- *
- * This library 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.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-/*
- * This interface defines the interactions between the Xen control
- * libraries and the OS facilities used to communicate with the
- * hypervisor.
- *
- * It is possible to override the default (native) implementation by
- * setting the XENCTRL_OSDEP environment variable to point to a
- * plugin library. Userspace can use this facility to intercept
- * hypervisor operations. This can be used e.g. to implement a
- * userspace simulator for Xen hypercalls.
- *
- * The plugin must contain a data structure:
- *  xc_osdep_info_t xc_osdep_info;
- *
- * xc_osdep_init:
- *   Must return a suitable struct xc_osdep_ops pointer or NULL on failure.
- */
-
-#ifndef XC_OSDEP_H
-#define XC_OSDEP_H
-
-/* Tell the Xen public headers we are a user-space tools build. */
-#ifndef __XEN_TOOLS__
-#define __XEN_TOOLS__ 1
-#endif
-
-#include <sys/mman.h>
-#include <sys/types.h>
-
-#include <xen/sys/privcmd.h>
-
-enum xc_osdep_type {
-    XC_OSDEP_PRIVCMD,
-};
-
-/* Opaque handle internal to the backend */
-typedef unsigned long xc_osdep_handle;
-
-#define XC_OSDEP_OPEN_ERROR ((xc_osdep_handle)-1)
-
-struct xc_osdep_ops
-{
-    /* Opens an interface.
-     *
-     * Must return an opaque handle on success or
-     * XC_OSDEP_OPEN_ERROR on failure
-     */
-    xc_osdep_handle (*open)(xc_interface *xch);
-
-    int (*close)(xc_interface *xch, xc_osdep_handle h);
-
-    union {
-        struct {
-            void *(*alloc_hypercall_buffer)(xc_interface *xch, xc_osdep_handle h, int npages);
-            void (*free_hypercall_buffer)(xc_interface *xch, xc_osdep_handle h, void *ptr, int npages);
-
-            int (*hypercall)(xc_interface *xch, xc_osdep_handle h, privcmd_hypercall_t *hypercall);
-
-            void *(*map_foreign_batch)(xc_interface *xch, xc_osdep_handle h, uint32_t dom, int prot,
-                                       xen_pfn_t *arr, int num);
-            void *(*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);
-            void *(*map_foreign_range)(xc_interface *xch, xc_osdep_handle h, uint32_t dom, int size, int prot,
-                                       unsigned long mfn);
-            void *(*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);
-        } privcmd;
-    } u;
-};
-typedef struct xc_osdep_ops xc_osdep_ops;
-
-typedef xc_osdep_ops *(*xc_osdep_init_fn)(xc_interface *xch, enum xc_osdep_type);
-
-struct xc_osdep_info
-{
-    /* Describes this backend. */
-    const char *name;
-
-    /* Returns ops function. */
-    xc_osdep_init_fn init;
-
-    /* True if this interface backs onto a fake Xen. */
-    int fake;
-
-    /* For internal use by loader. */
-    void *dl_handle;
-};
-typedef struct xc_osdep_info xc_osdep_info_t;
-
-/* All backends, including the builtin backend, must supply this structure. */
-extern xc_osdep_info_t xc_osdep_info;
-
-/* Stub for not yet converted OSes */
-void *xc_map_foreign_bulk_compat(xc_interface *xch, xc_osdep_handle h,
-                                 uint32_t dom, int prot,
-                                 const xen_pfn_t *arr, int *err, unsigned int num);
-
-/* Report errors through xc_interface */
-void xc_osdep_log(xc_interface *xch, xentoollog_level level, int code,
-                  const char *fmt, ...) __attribute__((format(printf, 4, 5)));
-
-#endif
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/tools/libxc/xc_foreign_memory.c b/tools/libxc/xc_foreign_memory.c
index 43abf01..53b6c9a 100644
--- a/tools/libxc/xc_foreign_memory.c
+++ b/tools/libxc/xc_foreign_memory.c
@@ -51,37 +51,8 @@ void *xc_map_foreign_pages(xc_interface *xch, uint32_t dom, int prot,
     return res;
 }
 
-void *xc_map_foreign_range(xc_interface *xch, uint32_t dom,
-                           int size, int prot, unsigned long mfn)
-{
-    return xch->ops->u.privcmd.map_foreign_range(xch, xch->ops_handle,
-                                                 dom, size, prot, mfn);
-}
-
-void *xc_map_foreign_ranges(xc_interface *xch, uint32_t dom,
-                            size_t size, int prot, size_t chunksize,
-                            privcmd_mmap_entry_t entries[], int nentries)
-{
-    return xch->ops->u.privcmd.map_foreign_ranges(xch, xch->ops_handle,
-                                                  dom, size, prot, chunksize, entries, nentries);
-}
-
-void *xc_map_foreign_batch(xc_interface *xch, uint32_t dom, int prot,
-                           xen_pfn_t *arr, int num)
-{
-    return xch->ops->u.privcmd.map_foreign_batch(xch, xch->ops_handle,
-                                                 dom, prot, arr, num);
-}
-
-void *xc_map_foreign_bulk(xc_interface *xch, uint32_t dom, int prot,
-                          const xen_pfn_t *arr, int *err, unsigned int num)
-{
-    return xch->ops->u.privcmd.map_foreign_bulk(xch, xch->ops_handle,
-                                                dom, prot, arr, err, num);
-}
-
 /* stub for all not yet converted OSes */
-void *xc_map_foreign_bulk_compat(xc_interface *xch, xc_osdep_handle h,
+void *xc_map_foreign_bulk_compat(xc_interface *xch,
                                  uint32_t dom, int prot,
                                  const xen_pfn_t *arr, int *err, unsigned int num)
 {
diff --git a/tools/libxc/xc_freebsd_osdep.c b/tools/libxc/xc_freebsd_osdep.c
index d948b37..4c0e2fd 100644
--- a/tools/libxc/xc_freebsd_osdep.c
+++ b/tools/libxc/xc_freebsd_osdep.c
@@ -33,16 +33,12 @@
 
 #include <xen/memory.h>
 
-#include "xenctrl.h"
-#include "xenctrlosdep.h"
+#include "xc_private.h"
 
 #define PRIVCMD_DEV     "/dev/xen/privcmd"
 
-#define PERROR(_m, _a...) xc_osdep_log(xch,XTL_ERROR,XC_INTERNAL_ERROR,_m \
-                  " (%d = %s)", ## _a , errno, xc_strerror(xch, errno))
-
 /*------------------------- Privcmd device interface -------------------------*/
-static xc_osdep_handle freebsd_privcmd_open(xc_interface *xch)
+int osdep_privcmd_open(xc_interface *xch)
 {
     int flags, saved_errno;
     int fd = open(PRIVCMD_DEV, O_RDWR);
@@ -51,7 +47,7 @@ static xc_osdep_handle freebsd_privcmd_open(xc_interface *xch)
     {
         PERROR("Could not obtain handle on privileged command interface "
                PRIVCMD_DEV);
-        return XC_OSDEP_OPEN_ERROR;
+        return -1
     }
 
     /*
@@ -74,27 +70,27 @@ static xc_osdep_handle freebsd_privcmd_open(xc_interface *xch)
         goto error;
     }
 
-    return (xc_osdep_handle)fd;
+    xch->privcmdfd = fd;
+    return 0;
 
  error:
     saved_errno = errno;
     close(fd);
     errno = saved_errno;
 
-    return XC_OSDEP_OPEN_ERROR;
+    return -1;
 }
 
-static int freebsd_privcmd_close(xc_interface *xch, xc_osdep_handle h)
+int osdep_privcmd_close(xc_interface *xch)
 {
-    int fd = (int)h;
-
+    int fd = xch->privcmdfd;
+    if ( fd == -1 )
+        return 0;
     return close(fd);
 }
 
 /*------------------------ Privcmd hypercall interface -----------------------*/
-static void *freebsd_privcmd_alloc_hypercall_buffer(xc_interface *xch,
-                                                    xc_osdep_handle h,
-                                                    int npages)
+void *osdep_alloc_hypercall_buffer(xc_interface *xch, int npages)
 {
     size_t size = npages * XC_PAGE_SIZE;
     void *p;
@@ -118,9 +114,7 @@ static void *freebsd_privcmd_alloc_hypercall_buffer(xc_interface *xch,
     return p;
 }
 
-static void freebsd_privcmd_free_hypercall_buffer(xc_interface *xch,
-                                                  xc_osdep_handle h, void *ptr,
-                                                  int npages)
+void osdep_free_hypercall_buffer(xc_interface *xch, void *ptr, int npages)
 {
 
     int saved_errno = errno;
@@ -132,10 +126,9 @@ static void freebsd_privcmd_free_hypercall_buffer(xc_interface *xch,
     errno = saved_errno;
 }
 
-static int freebsd_privcmd_hypercall(xc_interface *xch, xc_osdep_handle h,
-                                     privcmd_hypercall_t *hypercall)
+int do_xen_hypercall(xc_interface *xch, privcmd_hypercall_t *hypercall)
 {
-    int fd = (int)h;
+    int fd = xch->privcmdfd;
     int ret;
 
     ret = ioctl(fd, IOCTL_PRIVCMD_HYPERCALL, hypercall);
@@ -144,13 +137,12 @@ static int freebsd_privcmd_hypercall(xc_interface *xch, xc_osdep_handle h,
 }
 
 /*----------------------- Privcmd foreign map interface ----------------------*/
-static void *freebsd_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)
+void *xc_map_foreign_bulk(xc_interface *xch,
+                          uint32_t dom, int prot,
+                          const xen_pfn_t *arr, int *err,
+                          unsigned int num)
 {
-    int fd = (int)h;
+    int fd = xch->privcmdfd;
     privcmd_mmapbatch_t ioctlx;
     void *addr;
     int rc;
@@ -181,10 +173,9 @@ static void *freebsd_privcmd_map_foreign_bulk(xc_interface *xch,
     return addr;
 }
 
-static void *freebsd_privcmd_map_foreign_range(xc_interface *xch,
-                                               xc_osdep_handle h,
-                                               uint32_t dom, int size, int prot,
-                                               unsigned long mfn)
+void *xc_map_foreign_range(xc_interface *xch,
+                           uint32_t dom, int size, int prot,
+                           unsigned long mfn)
 {
     xen_pfn_t *arr;
     int num;
@@ -204,12 +195,11 @@ static void *freebsd_privcmd_map_foreign_range(xc_interface *xch,
     return ret;
 }
 
-static void *freebsd_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)
+void *xc_map_foreign_ranges(xc_interface *xch,
+                            uint32_t dom, size_t size,
+                            int prot, size_t chunksize,
+                            privcmd_mmap_entry_t entries[],
+                            int nentries)
 {
     xen_pfn_t *arr;
     int num_per_entry;
@@ -233,42 +223,6 @@ static void *freebsd_privcmd_map_foreign_ranges(xc_interface *xch,
     return ret;
 }
 
-/*----------------------------- Privcmd handlers -----------------------------*/
-static struct xc_osdep_ops freebsd_privcmd_ops = {
-    .open = &freebsd_privcmd_open,
-    .close = &freebsd_privcmd_close,
-
-    .u.privcmd = {
-        .alloc_hypercall_buffer = &freebsd_privcmd_alloc_hypercall_buffer,
-        .free_hypercall_buffer = &freebsd_privcmd_free_hypercall_buffer,
-
-        .hypercall = &freebsd_privcmd_hypercall,
-
-        .map_foreign_bulk = &freebsd_privcmd_map_foreign_bulk,
-        .map_foreign_range = &freebsd_privcmd_map_foreign_range,
-        .map_foreign_ranges = &freebsd_privcmd_map_foreign_ranges,
-    },
-};
-
-/*---------------------------- FreeBSD interface -----------------------------*/
-static struct xc_osdep_ops *
-freebsd_osdep_init(xc_interface *xch, enum xc_osdep_type type)
-{
-    switch ( type )
-    {
-    case XC_OSDEP_PRIVCMD:
-        return &freebsd_privcmd_ops;
-    default:
-        return NULL;
-    }
-}
-
-xc_osdep_info_t xc_osdep_info = {
-    .name = "FreeBSD Native OS interface",
-    .init = &freebsd_osdep_init,
-    .fake = 0,
-};
-
 /*
  * Local variables:
  * mode: C
diff --git a/tools/libxc/xc_hcall_buf.c b/tools/libxc/xc_hcall_buf.c
index 932b47c..ab8bee5 100644
--- a/tools/libxc/xc_hcall_buf.c
+++ b/tools/libxc/xc_hcall_buf.c
@@ -123,7 +123,7 @@ void xc__hypercall_buffer_cache_release(xc_interface *xch)
     while ( xch->hypercall_buffer_cache_nr > 0 )
     {
         p = xch->hypercall_buffer_cache[--xch->hypercall_buffer_cache_nr];
-        xch->ops->u.privcmd.free_hypercall_buffer(xch, xch->ops_handle, p, 1);
+        osdep_free_hypercall_buffer(xch, p, 1);
     }
 
     hypercall_buffer_cache_unlock(xch);
@@ -134,7 +134,7 @@ void *xc__hypercall_buffer_alloc_pages(xc_interface *xch, xc_hypercall_buffer_t
     void *p = hypercall_buffer_cache_alloc(xch, nr_pages);
 
     if ( !p )
-        p = xch->ops->u.privcmd.alloc_hypercall_buffer(xch, xch->ops_handle, nr_pages);
+        p = osdep_alloc_hypercall_buffer(xch, nr_pages);
 
     if (!p)
         return NULL;
@@ -152,7 +152,7 @@ void xc__hypercall_buffer_free_pages(xc_interface *xch, xc_hypercall_buffer_t *b
         return;
 
     if ( !hypercall_buffer_cache_free(xch, b->hbuf, nr_pages) )
-        xch->ops->u.privcmd.free_hypercall_buffer(xch, xch->ops_handle, b->hbuf, nr_pages);
+        osdep_free_hypercall_buffer(xch, b->hbuf, nr_pages);
 }
 
 struct allocation_header {
diff --git a/tools/libxc/xc_linux_osdep.c b/tools/libxc/xc_linux_osdep.c
index 7246b79..d17a52b 100644
--- a/tools/libxc/xc_linux_osdep.c
+++ b/tools/libxc/xc_linux_osdep.c
@@ -34,13 +34,12 @@
 #include <xen/memory.h>
 
 #include "xenctrl.h"
-#include "xenctrlosdep.h"
 
 #include "xc_private.h"
 
 #define ROUNDUP(_x,_w) (((unsigned long)(_x)+(1UL<<(_w))-1) & ~((1UL<<(_w))-1))
 
-static xc_osdep_handle linux_privcmd_open(xc_interface *xch)
+int osdep_privcmd_open(xc_interface *xch)
 {
     int flags, saved_errno;
     int fd = open("/proc/xen/privcmd", O_RDWR);
@@ -48,7 +47,7 @@ static xc_osdep_handle linux_privcmd_open(xc_interface *xch)
     if ( fd == -1 )
     {
         PERROR("Could not obtain handle on privileged command interface");
-        return XC_OSDEP_OPEN_ERROR;
+        return -1;
     }
 
     /* Although we return the file handle as the 'xc handle' the API
@@ -69,22 +68,25 @@ static xc_osdep_handle linux_privcmd_open(xc_interface *xch)
         goto error;
     }
 
-    return (xc_osdep_handle)fd;
+    xch->privcmdfd = fd;
+    return 0;
 
  error:
     saved_errno = errno;
     close(fd);
     errno = saved_errno;
-    return XC_OSDEP_OPEN_ERROR;
+    return -1;
 }
 
-static int linux_privcmd_close(xc_interface *xch, xc_osdep_handle h)
+int osdep_privcmd_close(xc_interface *xch)
 {
-    int fd = (int)h;
+    int fd = xch->privcmdfd;
+    if (fd == -1)
+        return 0;
     return close(fd);
 }
 
-static void *linux_privcmd_alloc_hypercall_buffer(xc_interface *xch, xc_osdep_handle h, int npages)
+void *osdep_alloc_hypercall_buffer(xc_interface *xch, int npages)
 {
     size_t size = npages * XC_PAGE_SIZE;
     void *p;
@@ -116,7 +118,7 @@ out:
     return NULL;
 }
 
-static void linux_privcmd_free_hypercall_buffer(xc_interface *xch, xc_osdep_handle h, void *ptr, int npages)
+void osdep_free_hypercall_buffer(xc_interface *xch, void *ptr, int npages)
 {
     int saved_errno = errno;
     /* Recover the VMA flags. Maybe it's not necessary */
@@ -127,9 +129,9 @@ static void linux_privcmd_free_hypercall_buffer(xc_interface *xch, xc_osdep_hand
     errno = saved_errno;
 }
 
-static int linux_privcmd_hypercall(xc_interface *xch, xc_osdep_handle h, privcmd_hypercall_t *hypercall)
+int do_xen_hypercall(xc_interface *xch, privcmd_hypercall_t *hypercall)
 {
-    int fd = (int)h;
+    int fd = xch->privcmdfd;
     return ioctl(fd, IOCTL_PRIVCMD_HYPERCALL, hypercall);
 }
 
@@ -155,11 +157,11 @@ static int xc_map_foreign_batch_single(int fd, uint32_t dom,
     return rc;
 }
 
-static void *linux_privcmd_map_foreign_batch(xc_interface *xch, xc_osdep_handle h,
-                                             uint32_t dom, int prot,
-                                             xen_pfn_t *arr, int num)
+void *xc_map_foreign_batch(xc_interface *xch,
+                           uint32_t dom, int prot,
+                           xen_pfn_t *arr, int num)
 {
-    int fd = (int)h;
+    int fd = xch->privcmdfd;
     privcmd_mmapbatch_t ioctlx;
     void *addr;
     int rc;
@@ -261,11 +263,11 @@ out:
     return rc;
 }
 
-static void *linux_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)
+void *xc_map_foreign_bulk(xc_interface *xch,
+                          uint32_t dom, int prot,
+                          const xen_pfn_t *arr, int *err, unsigned int num)
 {
-    int fd = (int)h;
+    int fd = xch->privcmdfd;
     privcmd_mmapbatch_v2_t ioctlx;
     void *addr;
     unsigned int i;
@@ -385,9 +387,9 @@ static void *linux_privcmd_map_foreign_bulk(xc_interface *xch, xc_osdep_handle h
     return addr;
 }
 
-static void *linux_privcmd_map_foreign_range(xc_interface *xch, xc_osdep_handle h,
-                                             uint32_t dom, int size, int prot,
-                                             unsigned long mfn)
+void *xc_map_foreign_range(xc_interface *xch,
+                           uint32_t dom, int size, int prot,
+                           unsigned long mfn)
 {
     xen_pfn_t *arr;
     int num;
@@ -407,10 +409,10 @@ static void *linux_privcmd_map_foreign_range(xc_interface *xch, xc_osdep_handle
     return ret;
 }
 
-static void *linux_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)
+void *xc_map_foreign_ranges(xc_interface *xch,
+                            uint32_t dom, size_t size, int prot,
+                            size_t chunksize, privcmd_mmap_entry_t entries[],
+                            int nentries)
 {
     xen_pfn_t *arr;
     int num_per_entry;
@@ -434,40 +436,6 @@ static void *linux_privcmd_map_foreign_ranges(xc_interface *xch, xc_osdep_handle
     return ret;
 }
 
-static struct xc_osdep_ops linux_privcmd_ops = {
-    .open = &linux_privcmd_open,
-    .close = &linux_privcmd_close,
-
-    .u.privcmd = {
-        .alloc_hypercall_buffer = &linux_privcmd_alloc_hypercall_buffer,
-        .free_hypercall_buffer = &linux_privcmd_free_hypercall_buffer,
-
-        .hypercall = &linux_privcmd_hypercall,
-
-        .map_foreign_batch = &linux_privcmd_map_foreign_batch,
-        .map_foreign_bulk = &linux_privcmd_map_foreign_bulk,
-        .map_foreign_range = &linux_privcmd_map_foreign_range,
-        .map_foreign_ranges = &linux_privcmd_map_foreign_ranges,
-    },
-};
-
-static struct xc_osdep_ops *linux_osdep_init(xc_interface *xch, enum xc_osdep_type type)
-{
-    switch ( type )
-    {
-    case XC_OSDEP_PRIVCMD:
-        return &linux_privcmd_ops;
-    default:
-        return NULL;
-    }
-}
-
-xc_osdep_info_t xc_osdep_info = {
-    .name = "Linux Native OS interface",
-    .init = &linux_osdep_init,
-    .fake = 0,
-};
-
 /*
  * Local variables:
  * mode: C
diff --git a/tools/libxc/xc_minios.c b/tools/libxc/xc_minios.c
index 947b19a..0a2ac5c 100644
--- a/tools/libxc/xc_minios.c
+++ b/tools/libxc/xc_minios.c
@@ -40,19 +40,20 @@ void minios_interface_close_fd(int fd);
 
 extern void minios_interface_close_fd(int fd);
 
-static xc_osdep_handle minios_privcmd_open(xc_interface *xch)
+int osdep_privcmd_open(xc_interface *xch)
 {
     int fd = alloc_fd(FTYPE_XC);
 
     if ( fd == -1)
-        return XC_OSDEP_OPEN_ERROR;
+        return -1;
 
-    return (xc_osdep_handle)fd;
+    xch->privcmdfd = fd;
+    return 0;
 }
 
-static int minios_privcmd_close(xc_interface *xch, xc_osdep_handle h)
+int osdep_privcmd_close(xc_interface *xch)
 {
-    int fd = (int)h;
+    int fd = xch->privcmdfd;
     return close(fd);
 }
 
@@ -61,17 +62,17 @@ void minios_interface_close_fd(int fd)
     files[fd].type = FTYPE_NONE;
 }
 
-static void *minios_privcmd_alloc_hypercall_buffer(xc_interface *xch, xc_osdep_handle h, int npages)
+void *osdep_alloc_hypercall_buffer(xc_interface *xch, int npages)
 {
     return xc_memalign(xch, PAGE_SIZE, npages * PAGE_SIZE);
 }
 
-static void minios_privcmd_free_hypercall_buffer(xc_interface *xch, xc_osdep_handle h, void *ptr, int npages)
+void osdep_free_hypercall_buffer(xc_interface *xch, void *ptr, int npages)
 {
     free(ptr);
 }
 
-static int minios_privcmd_hypercall(xc_interface *xch, xc_osdep_handle h, privcmd_hypercall_t *hypercall)
+int do_xen_hypercall(xc_interface *xch, privcmd_hypercall_t *hypercall)
 {
     multicall_entry_t call;
     int i, ret;
@@ -93,21 +94,21 @@ static int minios_privcmd_hypercall(xc_interface *xch, xc_osdep_handle h, privcm
     return call.result;
 }
 
-static void *minios_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)
+void *xc_map_foreign_bulk(xc_interface *xch,
+                          uint32_t dom, int prot,
+                          const xen_pfn_t *arr, int *err, unsigned int num)
 {
     unsigned long pt_prot = 0;
     if (prot & PROT_READ)
 	pt_prot = L1_PROT_RO;
     if (prot & PROT_WRITE)
 	pt_prot = L1_PROT;
-    return map_frames_ex(arr, num, 1, 0, 1, dom, err, pt_prot);    
+    return map_frames_ex(arr, num, 1, 0, 1, dom, err, pt_prot);
 }
 
-static void *minios_privcmd_map_foreign_batch(xc_interface *xch,  xc_osdep_handle h,
-                                              uint32_t dom, int prot,
-                                              xen_pfn_t *arr, int num)
+void *xc_map_foreign_batch(xc_interface *xch,
+                           uint32_t dom, int prot,
+                           xen_pfn_t *arr, int num)
 {
     unsigned long pt_prot = 0;
     int err[num];
@@ -127,10 +128,10 @@ static void *minios_privcmd_map_foreign_batch(xc_interface *xch,  xc_osdep_handl
     return (void *) addr;
 }
 
-static void *minios_privcmd_map_foreign_range(xc_interface *xch, xc_osdep_handle h,
-                                              uint32_t dom,
-                                              int size, int prot,
-                                              unsigned long mfn)
+void *xc_map_foreign_range(xc_interface *xch,
+                           uint32_t dom,
+                           int size, int prot,
+                           unsigned long mfn)
 {
     unsigned long pt_prot = 0;
 
@@ -143,10 +144,10 @@ static void *minios_privcmd_map_foreign_range(xc_interface *xch, xc_osdep_handle
     return map_frames_ex(&mfn, size / getpagesize(), 0, 1, 1, dom, NULL, pt_prot);
 }
 
-static void *minios_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)
+void *xc_map_foreign_ranges(xc_interface *xch,
+                            uint32_t dom,
+                            size_t size, int prot, size_t chunksize,
+                            privcmd_mmap_entry_t entries[], int nentries)
 {
     unsigned long *mfns;
     int i, j, n;
@@ -170,24 +171,6 @@ static void *minios_privcmd_map_foreign_ranges(xc_interface *xch, xc_osdep_handl
     return ret;
 }
 
-
-static struct xc_osdep_ops minios_privcmd_ops = {
-    .open = &minios_privcmd_open,
-    .close = &minios_privcmd_close,
-
-    .u.privcmd = {
-        .alloc_hypercall_buffer = &minios_privcmd_alloc_hypercall_buffer,
-        .free_hypercall_buffer = &minios_privcmd_free_hypercall_buffer,
-
-        .hypercall = &minios_privcmd_hypercall,
-
-        .map_foreign_batch = &minios_privcmd_map_foreign_batch,
-        .map_foreign_bulk = &minios_privcmd_map_foreign_bulk,
-        .map_foreign_range = &minios_privcmd_map_foreign_range,
-        .map_foreign_ranges = &minios_privcmd_map_foreign_ranges,
-    },
-};
-
 /* Optionally flush file to disk and discard page cache */
 void discard_file_cache(xc_interface *xch, int fd, int flush)
 {
@@ -200,23 +183,6 @@ void *xc_memalign(xc_interface *xch, size_t alignment, size_t size)
     return memalign(alignment, size);
 }
 
-static struct xc_osdep_ops *minios_osdep_init(xc_interface *xch, enum xc_osdep_type type)
-{
-    switch ( type )
-    {
-    case XC_OSDEP_PRIVCMD:
-        return &minios_privcmd_ops;
-    default:
-        return NULL;
-    }
-}
-
-xc_osdep_info_t xc_osdep_info = {
-    .name = "Minios Native OS interface",
-    .init = &minios_osdep_init,
-    .fake = 0,
-};
-
 /*
  * Local variables:
  * mode: C
diff --git a/tools/libxc/xc_netbsd.c b/tools/libxc/xc_netbsd.c
index 48fd5d7..5361f2b 100644
--- a/tools/libxc/xc_netbsd.c
+++ b/tools/libxc/xc_netbsd.c
@@ -25,7 +25,7 @@
 #include <malloc.h>
 #include <sys/mman.h>
 
-static xc_osdep_handle netbsd_privcmd_open(xc_interface *xch)
+int osdep_privcmd_open(xc_interface *xch)
 {
     int flags, saved_errno;
     int fd = open("/kern/xen/privcmd", O_RDWR);
@@ -33,7 +33,7 @@ static xc_osdep_handle netbsd_privcmd_open(xc_interface *xch)
     if ( fd == -1 )
     {
         PERROR("Could not obtain handle on privileged command interface");
-        return XC_OSDEP_OPEN_ERROR;
+        return -1;
     }
 
     /* Although we return the file handle as the 'xc handle' the API
@@ -52,22 +52,23 @@ static xc_osdep_handle netbsd_privcmd_open(xc_interface *xch)
         goto error;
     }
 
-    return (xc_osdep_handle)fd;
+    xch->privcmdfd = fd;
+    return 0;
 
  error:
     saved_errno = errno;
     close(fd);
     errno = saved_errno;
-    return XC_OSDEP_OPEN_ERROR;
+    return -1;
 }
 
-static int netbsd_privcmd_close(xc_interface *xch, xc_osdep_handle h)
+int osdep_privcmd_close(xc_interface *xch)
 {
-    int fd = (int)h;
+    int fd = xch->privcmdfd;
     return close(fd);
 }
 
-static void *netbsd_privcmd_alloc_hypercall_buffer(xc_interface *xch, xc_osdep_handle h, int npages)
+void *osdep_alloc_hypercall_buffer(xc_interface *xch, int npages)
 {
     size_t size = npages * XC_PAGE_SIZE;
     void *p;
@@ -84,15 +85,15 @@ static void *netbsd_privcmd_alloc_hypercall_buffer(xc_interface *xch, xc_osdep_h
     return p;
 }
 
-static void netbsd_privcmd_free_hypercall_buffer(xc_interface *xch, xc_osdep_handle h, void *ptr, int npages)
+void osdep_free_hypercall_buffer(xc_interface *xch, void *ptr, int npages)
 {
     (void) munlock(ptr, npages * XC_PAGE_SIZE);
     free(ptr);
 }
 
-static int netbsd_privcmd_hypercall(xc_interface *xch, xc_osdep_handle h, privcmd_hypercall_t *hypercall)
+int do_xen_hypercall(xc_interface *xch, privcmd_hypercall_t *hypercall)
 {
-    int fd = (int)h;
+    int fd = xch->privcmdfd;
     int error = ioctl(fd, IOCTL_PRIVCMD_HYPERCALL, hypercall);
 
     /*
@@ -107,11 +108,18 @@ static int netbsd_privcmd_hypercall(xc_interface *xch, xc_osdep_handle h, privcm
         return hypercall->retval;
 }
 
-static void *netbsd_privcmd_map_foreign_batch(xc_interface *xch, xc_osdep_handle h,
-                                              uint32_t dom, int prot,
-                                              xen_pfn_t *arr, int num)
+void *xc_map_foreign_bulk(xc_interface *xch,
+                          uint32_t dom, int prot,
+                          const xen_pfn_t *arr, int *err, unsigned int num)
 {
-    int fd = (int)h;
+    return xc_map_foreign_bulk_compat(xch, dom, prot, arr, err, num);
+}
+
+void *xc_map_foreign_batch(xc_interface *xch,
+                           uint32_t dom, int prot,
+                           xen_pfn_t *arr, int num)
+{
+    int fd = xch->privcmdfd;
     privcmd_mmapbatch_t ioctlx;
     void *addr;
     addr = mmap(NULL, num*XC_PAGE_SIZE, prot, MAP_ANON | MAP_SHARED, -1, 0);
@@ -136,12 +144,12 @@ static void *netbsd_privcmd_map_foreign_batch(xc_interface *xch, xc_osdep_handle
 
 }
 
-static void *netbsd_privcmd_map_foreign_range(xc_interface *xch, xc_osdep_handle h,
-                                              uint32_t dom,
-                                              int size, int prot,
-                                              unsigned long mfn)
+void *xc_map_foreign_range(xc_interface *xch,
+                           uint32_t dom,
+                           int size, int prot,
+                           unsigned long mfn)
 {
-    int fd = (int)h;
+    int fd = xch->privcmdfd;
     privcmd_mmap_t ioctlx;
     privcmd_mmap_entry_t entry;
     void *addr;
@@ -168,12 +176,12 @@ static void *netbsd_privcmd_map_foreign_range(xc_interface *xch, xc_osdep_handle
     return addr;
 }
 
-static void *netbsd_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)
+void *xc_map_foreign_ranges(xc_interface *xch,
+                            uint32_t dom,
+                            size_t size, int prot, size_t chunksize,
+                            privcmd_mmap_entry_t entries[], int nentries)
 {
-    int fd = (int)h;
+    int fd = xch->privcmdfd;
 	privcmd_mmap_t ioctlx;
 	int i, rc;
 	void *addr;
@@ -206,23 +214,6 @@ mmap_failed:
 	return NULL;
 }
 
-static struct xc_osdep_ops netbsd_privcmd_ops = {
-    .open = &netbsd_privcmd_open,
-    .close = &netbsd_privcmd_close,
-
-    .u.privcmd = {
-        .alloc_hypercall_buffer = &netbsd_privcmd_alloc_hypercall_buffer,
-        .free_hypercall_buffer = &netbsd_privcmd_free_hypercall_buffer,
-
-        .hypercall = &netbsd_privcmd_hypercall,
-
-        .map_foreign_batch = &netbsd_privcmd_map_foreign_batch,
-        .map_foreign_bulk = &xc_map_foreign_bulk_compat,
-        .map_foreign_range = &netbsd_privcmd_map_foreign_range,
-        .map_foreign_ranges = &netbsd_privcmd_map_foreign_ranges,
-    },
-};
-
 /* Optionally flush file to disk and discard page cache */
 void discard_file_cache(xc_interface *xch, int fd, int flush) 
 {
@@ -263,23 +254,6 @@ void *xc_memalign(xc_interface *xch, size_t alignment, size_t size)
     return valloc(size);
 }
 
-static struct xc_osdep_ops *netbsd_osdep_init(xc_interface *xch, enum xc_osdep_type type)
-{
-    switch ( type )
-    {
-    case XC_OSDEP_PRIVCMD:
-        return &netbsd_privcmd_ops;
-    default:
-        return NULL;
-    }
-}
-
-xc_osdep_info_t xc_osdep_info = {
-    .name = "Netbsd Native OS interface",
-    .init = &netbsd_osdep_init,
-    .fake = 0,
-};
-
 /*
  * Local variables:
  * mode: C
diff --git a/tools/libxc/xc_private.c b/tools/libxc/xc_private.c
index e411210..c56d748 100644
--- a/tools/libxc/xc_private.c
+++ b/tools/libxc/xc_private.c
@@ -27,111 +27,12 @@
 #include <pthread.h>
 #include <assert.h>
 
-#ifndef __MINIOS__
-#include <dlfcn.h>
-#endif
-
-#define XENCTRL_OSDEP "XENCTRL_OSDEP"
-
-#if !defined (__MINIOS__) && !defined(__RUMPUSER_XEN__) && !defined(__RUMPRUN__)
-#define DO_DYNAMIC_OSDEP
-#endif
-
-/*
- * Returns a (shallow) copy of the xc_osdep_info_t for the
- * active OS interface.
- *
- * On success a handle to the relevant library is opened.  The user
- * must subsequently call xc_osdep_put_info() when it is
- * finished with the library.
- *
- * Logs IFF xch != NULL.
- *
- * Returns:
- *  0 - on success
- * -1 - on error
- */
-static int xc_osdep_get_info(xc_interface *xch, xc_osdep_info_t *info)
-{
-    int rc = -1;
-#ifdef DO_DYNAMIC_OSDEP
-    const char *lib = getenv(XENCTRL_OSDEP);
-    xc_osdep_info_t *pinfo;
-    void *dl_handle = NULL;
-
-    if ( lib != NULL )
-    {
-        if ( getuid() != geteuid() )
-        {
-            if ( xch ) ERROR("cannot use %s=%s with setuid application", XENCTRL_OSDEP, lib);
-            abort();
-        }
-        if ( getgid() != getegid() )
-        {
-            if ( xch ) ERROR("cannot use %s=%s with setgid application", XENCTRL_OSDEP, lib);
-            abort();
-        }
-
-        dl_handle = dlopen(lib, RTLD_LAZY|RTLD_LOCAL);
-        if ( !dl_handle )
-        {
-            if ( xch ) ERROR("unable to open osdep library %s: %s", lib, dlerror());
-            goto out;
-        }
-
-        pinfo = dlsym(dl_handle, "xc_osdep_info");
-        if ( !pinfo )
-        {
-            if ( xch ) ERROR("unable to find xc_osinteface_info in %s: %s", lib, dlerror());
-            goto out;
-        }
-
-        *info = *pinfo;
-        info->dl_handle = dl_handle;
-    }
-    else
-#endif /*DO_DYNAMIC_OSDEP*/
-    {
-        *info = xc_osdep_info;
-        info->dl_handle = NULL;
-    }
-
-    rc = 0;
-
-#ifdef DO_DYNAMIC_OSDEP
-out:
-    if ( dl_handle && rc == -1 )
-        dlclose(dl_handle);
-#endif /*DO_DYNAMIC_OSDEP*/
-
-    return rc;
-}
-
-static void xc_osdep_put(xc_osdep_info_t *info)
-{
-#ifdef DO_DYNAMIC_OSDEP
-    if ( info->dl_handle )
-        dlclose(info->dl_handle);
-#endif /*DO_DYNAMIC_OSDEP*/
-}
-
-static const char *xc_osdep_type_name(enum xc_osdep_type type)
-{
-    switch ( type )
-    {
-    case XC_OSDEP_PRIVCMD: return "privcmd";
-    }
-    return "unknown";
-}
-
-static struct xc_interface_core *xc_interface_open_common(xentoollog_logger *logger,
-                                                          xentoollog_logger *dombuild_logger,
-                                                          unsigned open_flags,
-                                                          enum xc_osdep_type type)
+struct xc_interface_core *xc_interface_open(xentoollog_logger *logger,
+                                            xentoollog_logger *dombuild_logger,
+                                            unsigned open_flags)
 {
     struct xc_interface_core xch_buf, *xch = &xch_buf;
 
-    xch->type = type;
     xch->flags = open_flags;
     xch->dombuild_logger_file = 0;
     xc_clear_last_error(xch);
@@ -149,9 +50,6 @@ static struct xc_interface_core *xc_interface_open_common(xentoollog_logger *log
     xch->hypercall_buffer_cache_misses = 0;
     xch->hypercall_buffer_cache_toobig = 0;
 
-    xch->ops_handle = XC_OSDEP_OPEN_ERROR;
-    xch->ops = NULL;
-
     if (!xch->error_handler) {
         xch->error_handler = xch->error_handler_tofree =
             (xentoollog_logger*)
@@ -169,40 +67,26 @@ static struct xc_interface_core *xc_interface_open_common(xentoollog_logger *log
     *xch = xch_buf;
 
     if (!(open_flags & XC_OPENFLAG_DUMMY)) {
-        if ( xc_osdep_get_info(xch, &xch->osdep) < 0 )
+        if ( osdep_privcmd_open(xch) < 0 )
             goto err;
-
-        xch->ops = xch->osdep.init(xch, type);
-        if ( xch->ops == NULL )
-        {
-            DPRINTF("OSDEP: interface %d (%s) not supported on this platform",
-                  type, xc_osdep_type_name(type));
-            goto err_put_iface;
-        }
-
-        xch->ops_handle = xch->ops->open(xch);
-        if (xch->ops_handle == XC_OSDEP_OPEN_ERROR)
-            goto err_put_iface;
     }
 
     return xch;
 
-err_put_iface:
-    xc_osdep_put(&xch->osdep);
  err:
     xtl_logger_destroy(xch->error_handler_tofree);
     if (xch != &xch_buf) free(xch);
     return NULL;
 }
 
-static int xc_interface_close_common(xc_interface *xch)
+int xc_interface_close(xc_interface *xch)
 {
     int rc = 0;
 
     if (!xch)
-	return 0;
+        return 0;
 
-    rc = xch->ops->close(xch, xch->ops_handle);
+    rc = osdep_privcmd_close(xch);
     if (rc) PERROR("Could not close hypervisor interface");
 
     xc__hypercall_buffer_cache_release(xch);
@@ -214,42 +98,6 @@ static int xc_interface_close_common(xc_interface *xch)
     return rc;
 }
 
-int xc_interface_is_fake(void)
-{
-    xc_osdep_info_t info;
-
-    if ( xc_osdep_get_info(NULL, &info) < 0 )
-        return -1;
-
-    /* Have a copy of info so can release the interface now. */
-    xc_osdep_put(&info);
-
-    return info.fake;
-}
-
-xc_interface *xc_interface_open(xentoollog_logger *logger,
-                                xentoollog_logger *dombuild_logger,
-                                unsigned open_flags)
-{
-    xc_interface *xch;
-
-    xch = xc_interface_open_common(logger, dombuild_logger, open_flags,
-                                   XC_OSDEP_PRIVCMD);
-
-    return xch;
-}
-
-int xc_interface_close(xc_interface *xch)
-{
-    return xc_interface_close_common(xch);
-}
-
-
-int do_xen_hypercall(xc_interface *xch, privcmd_hypercall_t *hypercall)
-{
-    return xch->ops->u.privcmd.hypercall(xch, xch->ops_handle, hypercall);
-}
-
 static pthread_key_t errbuf_pkey;
 static pthread_once_t errbuf_pkey_once = PTHREAD_ONCE_INIT;
 
@@ -336,14 +184,6 @@ void xc_report_error(xc_interface *xch, int code, const char *fmt, ...)
     va_end(args);
 }
 
-void xc_osdep_log(xc_interface *xch, xentoollog_level level, int code, const char *fmt, ...)
-{
-    va_list args;
-    va_start(args, fmt);
-    xc_reportv(xch, xch->error_handler, level, code, fmt, args);
-    va_end(args);
-}
-
 const char *xc_set_progress_prefix(xc_interface *xch, const char *doing)
 {
     const char *old = xch->currently_progress_reporting;
diff --git a/tools/libxc/xc_private.h b/tools/libxc/xc_private.h
index 61f2f45..408b1be 100644
--- a/tools/libxc/xc_private.h
+++ b/tools/libxc/xc_private.h
@@ -31,7 +31,6 @@
 
 #include "_paths.h"
 #include "xenctrl.h"
-#include "xenctrlosdep.h"
 
 #include <xen/sys/privcmd.h>
 
@@ -89,7 +88,6 @@ struct iovec {
 #define MAX_PAGECACHE_USAGE (4*1024)
 
 struct xc_interface_core {
-    enum xc_osdep_type type;
     int flags;
     xentoollog_logger *error_handler,   *error_handler_tofree;
     xentoollog_logger *dombuild_logger, *dombuild_logger_tofree;
@@ -118,12 +116,21 @@ struct xc_interface_core {
     int hypercall_buffer_cache_misses;
     int hypercall_buffer_cache_toobig;
 
-    /* Low lovel OS interface */
-    xc_osdep_info_t  osdep;
-    xc_osdep_ops    *ops; /* backend operations */
-    xc_osdep_handle  ops_handle; /* opaque data for xc_osdep_ops */
+    /* Privcmd interface */
+    int privcmdfd;
 };
 
+int osdep_privcmd_open(xc_interface *xch);
+int osdep_privcmd_close(xc_interface *xch);
+
+void *osdep_alloc_hypercall_buffer(xc_interface *xch, int npages);
+void osdep_free_hypercall_buffer(xc_interface *xch, void *ptr, int npages);
+
+/* Stub for not yet converted OSes */
+void *xc_map_foreign_bulk_compat(xc_interface *xch,
+                                 uint32_t dom, int prot,
+                                 const xen_pfn_t *arr, int *err, unsigned int num);
+
 void xc_report_error(xc_interface *xch, int code, const char *fmt, ...)
     __attribute__((format(printf,3,4)));
 void xc_reportv(xc_interface *xch, xentoollog_logger *lg, xentoollog_level,
diff --git a/tools/libxc/xc_solaris.c b/tools/libxc/xc_solaris.c
index 182bd7d..d719a11 100644
--- a/tools/libxc/xc_solaris.c
+++ b/tools/libxc/xc_solaris.c
@@ -25,7 +25,7 @@
 #include <fcntl.h>
 #include <malloc.h>
 
-static xc_osdep_handle solaris_privcmd_open(xc_interface *xch)
+int osdep_privcmd_open(xc_interface *xch)
 {
     int flags, saved_errno;
     int fd = open("/dev/xen/privcmd", O_RDWR);
@@ -33,7 +33,7 @@ static xc_osdep_handle solaris_privcmd_open(xc_interface *xch)
     if ( fd == -1 )
     {
         PERROR("Could not obtain handle on privileged command interface");
-        return XC_OSDEP_OPEN_ERROR;
+        return -1;
     }
 
     /* Although we return the file handle as the 'xc handle' the API
@@ -52,42 +52,43 @@ static xc_osdep_handle solaris_privcmd_open(xc_interface *xch)
         goto error;
     }
 
-    return (xc_osdep_handle)fd;
+    xch->privcmdfd = fd;
+    return 0;
 
  error:
     saved_errno = errno;
     close(fd);
     errno = saved_errno;
-    return XC_OSDEP_OPEN_ERROR;
+    return -1;
 }
 
-static int solaris_privcmd_close(xc_interface *xch, xc_osdep_handle h)
+int osdep_privcmd_close(xc_interface *xch)
 {
-    int fd = (int)h;
+    int fd = xch->privcmdfd;
     return close(fd);
 }
 
-static void *solaris_privcmd_alloc_hypercall_buffer(xc_interface *xch, xc_osdep_handle h, int npages)
+void *osdep_alloc_hypercall_buffer(xc_interface *xch, int npages)
 {
     return xc_memalign(xch, XC_PAGE_SIZE, npages * XC_PAGE_SIZE);
 }
 
-static void solaris_privcmd_free_hypercall_buffer(xc_interface *xch, xc_osdep_handle h, void *ptr, int npages)
+static void osdep_free_hypercall_buffer(xc_interface *xch, void *ptr, int npages)
 {
     free(ptr);
 }
 
-static int solaris_privcmd_hypercall(xc_interface *xch, xc_osdep_handle h, privcmd_hypercall_t *hypercall)
+int do_xen_hypercall(xc_interface *xch, privcmd_hypercall_t *hypercall)
 {
-    int fd = (int)h;
+    int fd = xch->privcmdfd;
     return ioctl(fd, IOCTL_PRIVCMD_HYPERCALL, hypercall);
 }
 
-static void *solaris_privcmd_map_foreign_batch(xc_interface *xch, xc_osdep_handle h,
-                                               uint32_t dom, int prot,
-                                               xen_pfn_t *arr, int num)
+void *xc_map_foreign_batch(xc_interface *xch,
+                          uint32_t dom, int prot,
+                          xen_pfn_t *arr, int num)
 {
-    int fd = (int)h;
+    int fd = xch->privcmdfd;
     privcmd_mmapbatch_t ioctlx;
     void *addr;
     addr = mmap(NULL, num*XC_PAGE_SIZE, prot, MAP_SHARED, fd, 0);
@@ -110,12 +111,19 @@ static void *solaris_privcmd_map_foreign_batch(xc_interface *xch, xc_osdep_handl
 
 }
 
-static void *xc_map_foreign_range(xc_interface *xch, xc_osdep_handle h,
-                                  uint32_t dom,
-                                  int size, int prot,
-                                  unsigned long mfn)
+void *xc_map_foreign_bulk(xc_interface *xch,
+                          uint32_t dom, int prot,
+                          const xen_pfn_t *arr, int *err, unsigned int num)
 {
-    int fd = (int)fd;
+    return xc_map_foreign_bulk_compat(xch, dom, prot, arr, err, num);
+}
+
+void *xc_map_foreign_range(xc_interface *xch,
+                           uint32_t dom,
+                           int size, int prot,
+                           unsigned long mfn)
+{
+    int fd = xch->privcmdfd;
     privcmd_mmap_t ioctlx;
     privcmd_mmap_entry_t entry;
     void *addr;
@@ -139,12 +147,12 @@ static void *xc_map_foreign_range(xc_interface *xch, xc_osdep_handle h,
     return addr;
 }
 
-static void *solaric_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)
+void *xc_map_foreign_ranges(xc_interface *xch,
+                            uint32_t dom,
+                            size_t size, int prot, size_t chunksize,
+                            privcmd_mmap_entry_t entries[], int nentries)
 {
-    int fd = (int)fd;
+    int fd = xch->privcmdfd;
     privcmd_mmap_t ioctlx;
     int i, rc;
     void *addr;
@@ -177,23 +185,6 @@ mmap_failed:
     return NULL;
 }
 
-static struct xc_osdep_ops solaris_privcmd_ops = {
-    .open = &solaris_privcmd_open,
-    .close = &solaris_privcmd_close,
-
-    .u.privcmd = {
-        .alloc_hypercall_buffer = &solaris_privcmd_alloc_hypercall_buffer,
-        .free_hypercall_buffer = &solaris_privcmd_free_hypercall_buffer,
-
-        .hypercall = &solaris_privcmd_hypercall;
-
-        .map_foreign_batch = &solaris_privcmd_map_foreign_batch,
-        .map_foreign_bulk = &xc_map_foreign_bulk_compat,
-        .map_foreign_range = &solaris_privcmd_map_foreign_range,
-        .map_foreign_ranges = &solaris_privcmd_map_foreign_ranges,
-    },
-};
-
 /* Optionally flush file to disk and discard page cache */
 void discard_file_cache(xc_interface *xch, int fd, int flush) 
 {
@@ -205,23 +196,6 @@ void *xc_memalign(xc_interface *xch, size_t alignment, size_t size)
     return memalign(alignment, size);
 }
 
-static struct xc_osdep_ops *solaris_osdep_init(xc_interface *xch, enum xc_osdep_type type)
-{
-    switch ( type )
-    {
-    case XC_OSDEP_PRIVCMD:
-        return &solaris_privcmd_ops;
-    default:
-        return NULL;
-    }
-}
-
-xc_osdep_info_t xc_osdep_info = {
-    .name = "Solaris Native OS interface",
-    .init = &solaris_osdep_init,
-    .fake = 0,
-};
-
 /*
  * Local variables:
  * mode: C
diff --git a/tools/libxc/xenctrl_osdep_ENOSYS.c b/tools/libxc/xenctrl_osdep_ENOSYS.c
deleted file mode 100644
index 5182532..0000000
--- a/tools/libxc/xenctrl_osdep_ENOSYS.c
+++ /dev/null
@@ -1,123 +0,0 @@
-/* Dummy backend which just logs and returns ENOSYS. */
-
-#include <errno.h>
-#include <inttypes.h>
-#include <stdlib.h>
-
-#include "xenctrl.h"
-#include "xenctrlosdep.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))
-
-static xc_osdep_handle ENOSYS_privcmd_open(xc_interface *xch)
-{
-    IPRINTF(xch, "ENOSYS_privcmd: opening handle %d\n", 1);
-    return (xc_osdep_handle)1; /*dummy*/
-}
-
-static int ENOSYS_privcmd_close(xc_interface *xch, xc_osdep_handle h)
-{
-    IPRINTF(xch, "ENOSYS_privcmd: closing handle %lx\n", h);
-    return 0;
-}
-
-static int ENOSYS_privcmd_hypercall(xc_interface *xch, xc_osdep_handle h, privcmd_hypercall_t *hypercall)
-{
-#if defined(__FreeBSD__) || defined(__NetBSD__)
-    IPRINTF(xch, "ENOSYS_privcmd %lx: hypercall: %02lu(%#lx,%#lx,%#lx,%#lx,%#lx)\n",
-#else
-    IPRINTF(xch, "ENOSYS_privcmd %lx: hypercall: %02lld(%#llx,%#llx,%#llx,%#llx,%#llx)\n",
-#endif
-            h, hypercall->op,
-            hypercall->arg[0], hypercall->arg[1], hypercall->arg[2],
-            hypercall->arg[3], hypercall->arg[4]);
-    return -ENOSYS;
-}
-
-static void *ENOSYS_privcmd_map_foreign_batch(xc_interface *xch, xc_osdep_handle h, uint32_t dom, int prot,
-                                      xen_pfn_t *arr, int num)
-{
-    IPRINTF(xch, "ENOSYS_privcmd %lx: map_foreign_batch: dom%d prot %#x arr %p num %d\n", h, dom, prot, arr, num);
-    return MAP_FAILED;
-}
-
-static void *ENOSYS_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)
-{
-    IPRINTF(xch, "ENOSYS_privcmd %lx map_foreign_buld: dom%d prot %#x arr %p err %p num %d\n", h, dom, prot, arr, err, num);
-    return MAP_FAILED;
-}
-
-static void *ENOSYS_privcmd_map_foreign_range(xc_interface *xch, xc_osdep_handle h, uint32_t dom, int size, int prot,
-                                      unsigned long mfn)
-{
-    IPRINTF(xch, "ENOSYS_privcmd %lx map_foreign_range: dom%d size %#x prot %#x mfn %ld\n", h, dom, size, prot, mfn);
-    return MAP_FAILED;
-}
-
-static void *ENOSYS_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)
-{
-    IPRINTF(xch, "ENOSYS_privcmd %lx map_foreign_ranges: dom%d size %zd prot %#x chunksize %zd entries %p num %d\n", h, dom, size, prot, chunksize, entries, nentries);
-    return MAP_FAILED;
-}
-
-static struct xc_osdep_ops ENOSYS_privcmd_ops =
-{
-    .open      = &ENOSYS_privcmd_open,
-    .close     = &ENOSYS_privcmd_close,
-    .u.privcmd   = {
-        .hypercall = &ENOSYS_privcmd_hypercall,
-
-        .map_foreign_batch = &ENOSYS_privcmd_map_foreign_batch,
-        .map_foreign_bulk = &ENOSYS_privcmd_map_foreign_bulk,
-        .map_foreign_range = &ENOSYS_privcmd_map_foreign_range,
-        .map_foreign_ranges = &ENOSYS_privcmd_map_foreign_ranges,
-    }
-};
-
-static struct xc_osdep_ops * ENOSYS_osdep_init(xc_interface *xch, enum xc_osdep_type type)
-{
-    struct xc_osdep_ops *ops;
-
-    if (getenv("ENOSYS") == NULL)
-    {
-        PERROR(xch, "ENOSYS: not configured\n");
-        return NULL;
-    }
-
-    switch ( type )
-    {
-    case XC_OSDEP_PRIVCMD:
-        ops = &ENOSYS_privcmd_ops;
-        break;
-    default:
-        ops = NULL;
-        break;
-    }
-
-    IPRINTF(xch, "ENOSYS_osdep_init: initialising handle ops at %p\n", ops);
-
-    return ops;
-}
-
-xc_osdep_info_t xc_osdep_info = {
-    .name = "Pessimistic ENOSYS OS interface",
-    .init = &ENOSYS_osdep_init,
-    .fake = 1,
-};
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/tools/ocaml/libs/xc/xenctrl.ml b/tools/ocaml/libs/xc/xenctrl.ml
index b7ba8b7..701b66c 100644
--- a/tools/ocaml/libs/xc/xenctrl.ml
+++ b/tools/ocaml/libs/xc/xenctrl.ml
@@ -108,8 +108,6 @@ external sizeof_xen_pfn: unit -> int = "stub_sizeof_xen_pfn"
 external interface_open: unit -> handle = "stub_xc_interface_open"
 external interface_close: handle -> unit = "stub_xc_interface_close"
 
-external is_fake: unit -> bool = "stub_xc_interface_is_fake"
-
 let with_intf f =
 	let xc = interface_open () in
 	let r = try f xc with exn -> interface_close xc; raise exn in
diff --git a/tools/ocaml/libs/xc/xenctrl.mli b/tools/ocaml/libs/xc/xenctrl.mli
index bc4af56..3f4947c 100644
--- a/tools/ocaml/libs/xc/xenctrl.mli
+++ b/tools/ocaml/libs/xc/xenctrl.mli
@@ -72,7 +72,6 @@ external sizeof_vcpu_guest_context : unit -> int
   = "stub_sizeof_vcpu_guest_context"
 external sizeof_xen_pfn : unit -> int = "stub_sizeof_xen_pfn"
 external interface_open : unit -> handle = "stub_xc_interface_open"
-external is_fake : unit -> bool = "stub_xc_interface_is_fake"
 external interface_close : handle -> unit = "stub_xc_interface_close"
 val with_intf : (handle -> 'a) -> 'a
 val domain_create : handle -> int32 -> domain_create_flag list -> string -> domid
diff --git a/tools/ocaml/libs/xc/xenctrl_stubs.c b/tools/ocaml/libs/xc/xenctrl_stubs.c
index 64f1137..9a201ee 100644
--- a/tools/ocaml/libs/xc/xenctrl_stubs.c
+++ b/tools/ocaml/libs/xc/xenctrl_stubs.c
@@ -126,13 +126,6 @@ CAMLprim value stub_xc_interface_open(void)
 }
 
 
-CAMLprim value stub_xc_interface_is_fake(void)
-{
-	CAMLparam0();
-	int is_fake = xc_interface_is_fake();
-	CAMLreturn(Val_int(is_fake));
-}
-
 CAMLprim value stub_xc_interface_close(value xch)
 {
 	CAMLparam1(xch);
diff --git a/tools/ocaml/xenstored/domains.ml b/tools/ocaml/xenstored/domains.ml
index 92e438f..395f3a9 100644
--- a/tools/ocaml/xenstored/domains.ml
+++ b/tools/ocaml/xenstored/domains.ml
@@ -65,11 +65,9 @@ let create xc doms domid mfn port =
 	Domain.bind_interdomain dom;
 	dom
 
-let create0 fake doms =
+let create0 doms =
 	let port, interface =
-		if fake then (
-			0, Xenctrl.with_intf (fun xc -> Xenctrl.map_foreign_range xc 0 (Xenmmap.getpagesize()) 0n)
-		) else (
+		(
 			let port = Utils.read_file_single_integer Define.xenstored_proc_port
 			and fd = Unix.openfile Define.xenstored_proc_kva
 					       [ Unix.O_RDWR ] 0o600 in
diff --git a/tools/ocaml/xenstored/xenstored.ml b/tools/ocaml/xenstored/xenstored.ml
index bfe689b..5c7ace1 100644
--- a/tools/ocaml/xenstored/xenstored.ml
+++ b/tools/ocaml/xenstored/xenstored.ml
@@ -176,7 +176,7 @@ let from_channel store cons doms chan =
 			if domid > 0 then
 				Domains.create xc doms domid mfn port
 			else
-				Domains.create0 false doms
+				Domains.create0 doms
 			in
 		Connections.add_domain cons ndom;
 		in
@@ -278,8 +278,7 @@ let _ =
 			Store.mkdir store (Perms.Connection.create 0) localpath;
 
 		if cf.domain_init then (
-			let usingxiu = Xenctrl.is_fake () in
-			Connections.add_domain cons (Domains.create0 usingxiu domains);
+			Connections.add_domain cons (Domains.create0 domains);
 			Event.bind_dom_exc_virq eventchn
 		);
 	);
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH XEN v2 10/15] tools: Refactor hypercall calling wrappers into libxencall.
  2015-07-15 15:46 [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries Ian Campbell
                   ` (8 preceding siblings ...)
  2015-07-15 15:46 ` [PATCH XEN v2 09/15] tools/libxc: Remove osdep indirection for privcmd Ian Campbell
@ 2015-07-15 15:46 ` Ian Campbell
  2015-07-15 15:46 ` [PATCH XEN v2 11/15] tools/libxc: drop xc_map_foreign_bulk_compat wrappers Ian Campbell
                   ` (17 subsequent siblings)
  27 siblings, 0 replies; 55+ messages in thread
From: Ian Campbell @ 2015-07-15 15:46 UTC (permalink / raw)
  To: ian.jackson, wei.liu2, xen-devel
  Cc: roger.pau, Ian Campbell, stefano.stabellini

libxencall will provide a stable API and ABI for calling hypercalls
(although those hypercalls themselves may not have a stable API). As
well as the hypercall buffer infrastructure needed in order to safely
provide pointer arguments to hypercalls.

libxenctrl encapsulates a instance of this interface, so users of that
library are not currently subjected to any actual changes. However all
hypercalls made internally by libxc now use the correct interface. It
is expected that most users of this library will be other libraries
providing a higher level interface, rather than applications directly.

Only the basic functionality to allocate hypercall safe memory is
moved, the type safe stuff and bounce buffers remain in libxc.

Note that the functionality to map foreign pages using privcmd is not
yet moved, meaning that an xc_interface will now contain two open
privcmd file descriptors. Foreign memory mapping is logically separate
functionality and will be moved into its own library.

The new library uses a version script to ensure that only expected
symbols are exported and to version them such that ABI guarantees can
be kept in the future.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
---

Must be applied with:
  - "qemu-xen-traditional: Add libxencall to rpath-link" and a
    corresponding QEMU_TAG update folded here.
  - "mini-os: Include libxencall with libxc" and a corresponding bump
    to MINIOS_UPSTREAM_REVISION folded in here.
---
 .gitignore                              |   2 +
 docs/misc/toolstack-library-abis.pandoc |  29 +++--
 stubdom/Makefile                        |  19 +++-
 tools/Makefile                          |   2 +
 tools/Rules.mk                          |   7 +-
 tools/libxc/Makefile                    |   7 +-
 tools/libxc/xc_domain.c                 | 105 ++++++------------
 tools/libxc/xc_evtchn.c                 |   9 +-
 tools/libxc/xc_flask.c                  |   8 +-
 tools/libxc/xc_freebsd_osdep.c          |  47 --------
 tools/libxc/xc_gnttab.c                 |   9 +-
 tools/libxc/xc_hcall_buf.c              | 138 +----------------------
 tools/libxc/xc_kexec.c                  |  36 ++----
 tools/libxc/xc_linux_osdep.c            |  49 ---------
 tools/libxc/xc_minios.c                 |  32 ------
 tools/libxc/xc_misc.c                   |  79 +++++--------
 tools/libxc/xc_netbsd.c                 |  40 -------
 tools/libxc/xc_private.c                |  64 +++++------
 tools/libxc/xc_private.h                |  76 ++++---------
 tools/libxc/xc_solaris.c                |  16 ---
 tools/libxc/xc_tmem.c                   |   7 +-
 tools/libxencall/Makefile               |  67 +++++++++++
 tools/libxencall/buffer.c               | 189 ++++++++++++++++++++++++++++++++
 tools/libxencall/core.c                 | 141 ++++++++++++++++++++++++
 tools/libxencall/freebsd.c              | 137 +++++++++++++++++++++++
 tools/libxencall/include/xencall.h      |  81 ++++++++++++++
 tools/libxencall/libxencall.map         |  19 ++++
 tools/libxencall/linux.c                | 129 ++++++++++++++++++++++
 tools/libxencall/minios.c               |  78 +++++++++++++
 tools/libxencall/netbsd.c               | 118 ++++++++++++++++++++
 tools/libxencall/private.h              |  68 ++++++++++++
 tools/libxencall/solaris.c              |  94 ++++++++++++++++
 tools/misc/Makefile                     |   4 +-
 tools/xcutils/Makefile                  |   2 +-
 tools/xenpaging/Makefile                |   2 +-
 35 files changed, 1316 insertions(+), 594 deletions(-)
 create mode 100644 tools/libxencall/Makefile
 create mode 100644 tools/libxencall/buffer.c
 create mode 100644 tools/libxencall/core.c
 create mode 100644 tools/libxencall/freebsd.c
 create mode 100644 tools/libxencall/include/xencall.h
 create mode 100644 tools/libxencall/libxencall.map
 create mode 100644 tools/libxencall/linux.c
 create mode 100644 tools/libxencall/minios.c
 create mode 100644 tools/libxencall/netbsd.c
 create mode 100644 tools/libxencall/private.h
 create mode 100644 tools/libxencall/solaris.c

diff --git a/.gitignore b/.gitignore
index 8cbd177..5841570 100644
--- a/.gitignore
+++ b/.gitignore
@@ -62,6 +62,7 @@ stubdom/xenstore
 stubdom/libxentoollog-*
 stubdom/libxenevtchn-*
 stubdom/libxengnttab-*
+stubdom/libxencall-*
 stubdom/libxc-*
 stubdom/lwip-*
 stubdom/mini-os-*
@@ -91,6 +92,7 @@ config/Docs.mk
 tools/libxentoollog/headers.chk
 tools/libxenevtchn/headers.chk
 tools/libxengnttab/headers.chk
+tools/libxencall/headers.chk
 tools/blktap2/daemon/blktapctrl
 tools/blktap2/drivers/img2qcow
 tools/blktap2/drivers/lock-util
diff --git a/docs/misc/toolstack-library-abis.pandoc b/docs/misc/toolstack-library-abis.pandoc
index d1550a6..8339834 100644
--- a/docs/misc/toolstack-library-abis.pandoc
+++ b/docs/misc/toolstack-library-abis.pandoc
@@ -151,6 +151,21 @@ Interface                         Underlying interface           Known external
 `xengnt???_*_notify` also use `IOCTL_GNTALLOC_SET_UNMAP_NOTIFY`,
 `IOCTL_GNTALLOC_SET_UNMAP_NOTIFY`, etc
 
+## `libxencall`: making hypercalls
+
+Making hypercalls and allocating suitable memory to use as hypercall
+pointer ("GUEST_HANDLE") arguments.
+
+Interface                         Underlying interface           Known external users
+--------------------------------- ------------------------------ --------------------
+`xencall_open`                    `open(2)`
+`xencall_close`                   `close(2)`
+`xencall0`, ..., `xencall5`       `IOCTL_PRIVCMD_HYPERCALL`
+`xencall_alloc_buffer`            `xencall_alloc_buffer_pages`
+`xencall_alloc_buffer_pages`      `mmap(2)`, `madvise(2)`
+`xencall_free_buffer`             `xencall_free_buffer_pages`
+`xencall_free_buffer_pages`       `munmap(2)`, `madvise(2)`
+
 # Unstable libraries
 
 These libraries do not provide a stable interface and are required to
@@ -217,12 +232,6 @@ Interface                         Underlying interface           Known external
 
 ### Hypercalls
 
-#### Making hypercalls
-
-Interface                         Underlying interface           Known external users
---------------------------------- ------------------------------ --------------------
-`do_xen_hypercall`                `IOCTL_PRIVCMD_HYPERCALL`      private
-
 #### Wrappers
 
 Interface                         Known in-tree users           Known external users
@@ -440,7 +449,7 @@ Symbols:
     - xc_getcpuinfo
     - xc_get_cpumap_size
     - xc_get_device_group
-    - xc_get_hvm_param
+    - xc_get_hvm_param (Legacy, replaced by `xc_hvm_param_get`)
     - xc_get_last_error
     - xc_get_machine_memory_map. Used by kexec-tools
     - xc_get_max_cpus. Used by kexec-tools
@@ -460,8 +469,8 @@ Symbols:
     - xc_hvm_map_io_range_to_ioreq_server
     - xc_hvm_map_pcidev_to_ioreq_server
     - xc_hvm_modified_memory (`HVMOP_modified_memory`). Used by qemu-dm.
-    - xc_hvm_param_get
-    - xc_hvm_param_set
+    - xc_hvm_param_get (`HVMOP_get_param`)
+    - xc_hvm_param_set (`HVMOP_set_param`)
     - xc_hvm_set_ioreq_server_state
     - xc_hvm_set_isa_irq_level (`HVMOP_set_isa_irq_level`). Used by qemu-dm.
     - xc_hvm_set_mem_type (`HVMOP_set_mem_type`). Used by qemu-dm.
@@ -559,7 +568,7 @@ Symbols:
     - xc_set_cpufreq_gov
     - xc_set_cpufreq_para
     - xc_set_cpuidle_max_cstate
-    - xc_set_hvm_param (`HVMOP_set_param`). Used by qemu-dm.
+    - xc_set_hvm_param (`HVMOP_set_param`, legacy, replaced by `xc_hvm_param_set`). Used by qemu-dm.
     - xc_set_mem_access
     - xc_set_progress_prefix
     - xc_set_sched_opt_smt
diff --git a/stubdom/Makefile b/stubdom/Makefile
index 7eab97f..ec058ca 100644
--- a/stubdom/Makefile
+++ b/stubdom/Makefile
@@ -330,6 +330,12 @@ mk-headers-$(XEN_TARGET_ARCH): $(IOEMU_LINKFARM_TARGET)
 	  ln -sf $(XEN_ROOT)/tools/libxengnttab/include/*.h include/ && \
 	  ln -sf $(XEN_ROOT)/tools/libxengnttab/*.c . && \
 	  ln -sf $(XEN_ROOT)/tools/libxengnttab/Makefile . )
+	mkdir -p libxencall-$(XEN_TARGET_ARCH)/include
+	[ -h libxencall-$(XEN_TARGET_ARCH)/Makefile ] || ( cd libxencall-$(XEN_TARGET_ARCH) && \
+	  ln -sf $(XEN_ROOT)/tools/libxencall/*.h . && \
+	  ln -sf $(XEN_ROOT)/tools/libxencall/include/*.h include/ && \
+	  ln -sf $(XEN_ROOT)/tools/libxencall/*.c . && \
+	  ln -sf $(XEN_ROOT)/tools/libxencall/Makefile . )
 	mkdir -p libxc-$(XEN_TARGET_ARCH)
 	[ -h libxc-$(XEN_TARGET_ARCH)/Makefile ] || ( cd libxc-$(XEN_TARGET_ARCH) && \
 	  ln -sf $(XEN_ROOT)/tools/libxc/*.h . && \
@@ -386,12 +392,23 @@ libxengnttab-$(XEN_TARGET_ARCH)/libxengnttab.a: $(NEWLIB_STAMPFILE)
 	CPPFLAGS="$(TARGET_CPPFLAGS)" CFLAGS="$(TARGET_CFLAGS)" $(MAKE) DESTDIR= -C libxengnttab-$(XEN_TARGET_ARCH)
 
 #######
+# libxencall
+#######
+
+.PHONY: libxencall
+libxencall: libxencall-$(XEN_TARGET_ARCH)/libxencall.a
+libxencall-$(XEN_TARGET_ARCH)/libxencall.a: $(NEWLIB_STAMPFILE)
+	$(MAKE) -C $(XEN_ROOT)/tools/include
+	$(MAKE) DESTDIR= -C $(MINI_OS) links
+	CPPFLAGS="$(TARGET_CPPFLAGS)" CFLAGS="$(TARGET_CFLAGS)" $(MAKE) DESTDIR= -C libxencall-$(XEN_TARGET_ARCH)
+
+#######
 # libxc
 #######
 
 .PHONY: libxc
 libxc: libxc-$(XEN_TARGET_ARCH)/libxenctrl.a libxc-$(XEN_TARGET_ARCH)/libxenguest.a
-libxc-$(XEN_TARGET_ARCH)/libxenctrl.a: libxentoollog libxenevtchn libxengnttab cross-zlib
+libxc-$(XEN_TARGET_ARCH)/libxenctrl.a: libxentoollog libxenevtchn libxengnttab libxencall cross-zlib
 	$(MAKE) -C $(XEN_ROOT)/tools/include
 	$(MAKE) DESTDIR= -C $(MINI_OS) links
 	CPPFLAGS="$(TARGET_CPPFLAGS)" CFLAGS="$(TARGET_CFLAGS)" $(MAKE) DESTDIR= CONFIG_LIBXC_MINIOS=y -C libxc-$(XEN_TARGET_ARCH)
diff --git a/tools/Makefile b/tools/Makefile
index d3bf571..e5c8879 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -6,6 +6,7 @@ SUBDIRS-y += include
 SUBDIRS-y += libxentoollog
 SUBDIRS-y += libxenevtchn
 SUBDIRS-y += libxengnttab
+SUBDIRS-y += libxencall
 SUBDIRS-y += libxc
 SUBDIRS-$(FLASK_ENABLE) += flask
 SUBDIRS-y += xenstore
@@ -265,6 +266,7 @@ subdir-all-qemu-xen-dir: qemu-xen-dir-find
 		-Wl,-rpath-link=$(XEN_ROOT)/tools/libxentoollog \
 		-Wl,-rpath-link=$(XEN_ROOT)/tools/libxenevtchn \
 		-Wl,-rpath-link=$(XEN_ROOT)/tools/libxengnttab \
+		-Wl,-rpath-link=$(XEN_ROOT)/tools/libxencall \
 		$(QEMU_UPSTREAM_RPATH)" \
 		--bindir=$(LIBEXEC_BIN) \
 		--datadir=$(SHAREDIR)/qemu-xen \
diff --git a/tools/Rules.mk b/tools/Rules.mk
index e3923e2..405a6a5 100644
--- a/tools/Rules.mk
+++ b/tools/Rules.mk
@@ -13,6 +13,7 @@ XEN_INCLUDE        = $(XEN_ROOT)/tools/include
 XEN_LIBXENTOOLLOG  = $(XEN_ROOT)/tools/libxentoollog
 XEN_LIBXENEVTCHN   = $(XEN_ROOT)/tools/libxenevtchn
 XEN_LIBXENGNTTAB   = $(XEN_ROOT)/tools/libxengnttab
+XEN_LIBXENCALL     = $(XEN_ROOT)/tools/libxencall
 XEN_LIBXC          = $(XEN_ROOT)/tools/libxc
 XEN_XENLIGHT       = $(XEN_ROOT)/tools/libxl
 XEN_XENSTORE       = $(XEN_ROOT)/tools/xenstore
@@ -98,8 +99,12 @@ CFLAGS_libxengntshr = -I$(XEN_LIBXENGNTTAB)/include $(CFLAGS_xeninclude)
 LDLIBS_libxengntshr = $(XEN_LIBXENGNTTAB)/libxengnttab$(libextension)
 SHLIB_libxengntshr  = -Wl,-rpath-link=$(XEN_LIBXENGNTTAB)
 
+CFLAGS_libxencall = -I$(XEN_LIBXENCALL)/include $(CFLAGS_xeninclude)
+LDLIBS_libxencall = $(XEN_LIBXENCALL)/libxencall$(libextension)
+SHLIB_libxencall  = -Wl,-rpath-link=$(XEN_LIBXENCALL)
+
 CFLAGS_libxenctrl = -I$(XEN_LIBXC)/include $(CFLAGS_libxentoollog) $(CFLAGS_xeninclude)
-SHDEPS_libxenctrl = $(SHLIB_libxentoollog) $(SHLIB_libxenevtchn) $(SHLIB_libxengnttab) $(SHLIB_libxengntshr)
+SHDEPS_libxenctrl = $(SHLIB_libxentoollog) $(SHLIB_libxenevtchn) $(SHLIB_libxengnttab) $(SHLIB_libxengntshr) $(SHLIB_libxencall)
 LDLIBS_libxenctrl = $(SHDEPS_libxenctrl) $(XEN_LIBXC)/libxenctrl$(libextension)
 SHLIB_libxenctrl  = $(SHDEPS_libxenctrl) -Wl,-rpath-link=$(XEN_LIBXC)
 
diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile
index 77d2ae1..42fbabe 100644
--- a/tools/libxc/Makefile
+++ b/tools/libxc/Makefile
@@ -123,6 +123,11 @@ GUEST_PIC_OBJS := $(patsubst %.c,%.opic,$(GUEST_SRCS-y))
 $(CTRL_LIB_OBJS) $(GUEST_LIB_OBJS) \
 $(CTRL_PIC_OBJS) $(GUEST_PIC_OBJS): CFLAGS += -include $(XEN_ROOT)/tools/config.h
 
+# libxenguest includes xc_private.h, so needs this despite not using
+# this functionality directly.
+$(CTRL_LIB_OBJS) $(GUEST_LIB_OBJS) \
+$(CTRL_PIC_OBJS) $(GUEST_PIC_OBJS): CFLAGS += $(CFLAGS_libxencall)
+
 $(CTRL_LIB_OBJS) $(CTRL_PIC_OBJS): CFLAGS += $(CFLAGS_libxengnttab) $(CFLAGS_libxengntshr)
 
 LIB := libxenctrl.a
@@ -203,7 +208,7 @@ libxenctrl.so.$(MAJOR): libxenctrl.so.$(MAJOR).$(MINOR)
 	$(SYMLINK_SHLIB) $< $@
 
 libxenctrl.so.$(MAJOR).$(MINOR): $(CTRL_PIC_OBJS)
-	$(CC) $(LDFLAGS) $(PTHREAD_LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenctrl.so.$(MAJOR) $(SHLIB_LDFLAGS) -o $@ $^ $(LDLIBS_libxentoollog) $(LDLIBS_libxenevtchn) $(LDLIBS_libxengnttab) $(LDLIBS_libxengntshr) $(PTHREAD_LIBS) $(APPEND_LDFLAGS)
+	$(CC) $(LDFLAGS) $(PTHREAD_LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenctrl.so.$(MAJOR) $(SHLIB_LDFLAGS) -o $@ $^ $(LDLIBS_libxentoollog) $(LDLIBS_libxenevtchn) $(LDLIBS_libxengnttab) $(LDLIBS_libxengntshr) $(LDLIBS_libxencall) $(PTHREAD_LIBS) $(APPEND_LDFLAGS)
 
 # libxenguest
 
diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c
index 6db8d13..bda0173 100644
--- a/tools/libxc/xc_domain.c
+++ b/tools/libxc/xc_domain.c
@@ -132,7 +132,6 @@ int xc_domain_shutdown(xc_interface *xch,
                        int reason)
 {
     int ret = -1;
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(sched_remote_shutdown_t, arg);
 
     arg = xc_hypercall_buffer_alloc(xch, arg, sizeof(*arg));
@@ -142,13 +141,11 @@ int xc_domain_shutdown(xc_interface *xch,
         goto out1;
     }
 
-    hypercall.op     = __HYPERVISOR_sched_op;
-    hypercall.arg[0] = (unsigned long)SCHEDOP_remote_shutdown;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
     arg->domain_id = domid;
     arg->reason = reason;
-
-    ret = do_xen_hypercall(xch, &hypercall);
+    ret = xencall2(xch->xcall, __HYPERVISOR_sched_op,
+                   SCHEDOP_remote_shutdown,
+                   HYPERCALL_BUFFER_AS_ARG(arg));
 
     xc_hypercall_buffer_free(xch, arg);
 
@@ -571,7 +568,6 @@ int xc_watchdog(xc_interface *xch,
                 uint32_t timeout)
 {
     int ret = -1;
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(sched_watchdog_t, arg);
 
     arg = xc_hypercall_buffer_alloc(xch, arg, sizeof(*arg));
@@ -581,13 +577,12 @@ int xc_watchdog(xc_interface *xch,
         goto out1;
     }
 
-    hypercall.op     = __HYPERVISOR_sched_op;
-    hypercall.arg[0] = (unsigned long)SCHEDOP_watchdog;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
     arg->id = id;
     arg->timeout = timeout;
 
-    ret = do_xen_hypercall(xch, &hypercall);
+    ret = xencall2(xch->xcall, __HYPERVISOR_sched_op,
+                   SCHEDOP_watchdog,
+                   HYPERCALL_BUFFER_AS_ARG(arg));
 
     xc_hypercall_buffer_free(xch, arg);
 
@@ -1330,7 +1325,6 @@ static inline int xc_hvm_param_deprecated_check(uint32_t param)
 
 int xc_hvm_param_set(xc_interface *handle, domid_t dom, uint32_t param, uint64_t value)
 {
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(xen_hvm_param_t, arg);
     int rc = xc_hvm_param_deprecated_check(param);
 
@@ -1341,20 +1335,18 @@ int xc_hvm_param_set(xc_interface *handle, domid_t dom, uint32_t param, uint64_t
     if ( arg == NULL )
         return -1;
 
-    hypercall.op     = __HYPERVISOR_hvm_op;
-    hypercall.arg[0] = HVMOP_set_param;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
     arg->domid = dom;
     arg->index = param;
     arg->value = value;
-    rc = do_xen_hypercall(handle, &hypercall);
+    rc = xencall2(handle->xcall, __HYPERVISOR_hvm_op,
+                  HVMOP_set_param,
+                  HYPERCALL_BUFFER_AS_ARG(arg));
     xc_hypercall_buffer_free(handle, arg);
     return rc;
 }
 
 int xc_hvm_param_get(xc_interface *handle, domid_t dom, uint32_t param, uint64_t *value)
 {
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(xen_hvm_param_t, arg);
     int rc = xc_hvm_param_deprecated_check(param);
 
@@ -1365,12 +1357,11 @@ int xc_hvm_param_get(xc_interface *handle, domid_t dom, uint32_t param, uint64_t
     if ( arg == NULL )
         return -1;
 
-    hypercall.op     = __HYPERVISOR_hvm_op;
-    hypercall.arg[0] = HVMOP_get_param;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
     arg->domid = dom;
     arg->index = param;
-    rc = do_xen_hypercall(handle, &hypercall);
+    rc = xencall2(handle->xcall, __HYPERVISOR_hvm_op,
+                  HVMOP_get_param,
+                  HYPERCALL_BUFFER_AS_ARG(arg));
     *value = arg->value;
     xc_hypercall_buffer_free(handle, arg);
     return rc;
@@ -1398,7 +1389,6 @@ int xc_hvm_create_ioreq_server(xc_interface *xch,
                                int handle_bufioreq,
                                ioservid_t *id)
 {
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(xen_hvm_create_ioreq_server_t, arg);
     int rc;
 
@@ -1406,14 +1396,12 @@ int xc_hvm_create_ioreq_server(xc_interface *xch,
     if ( arg == NULL )
         return -1;
 
-    hypercall.op     = __HYPERVISOR_hvm_op;
-    hypercall.arg[0] = HVMOP_create_ioreq_server;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
-
     arg->domid = domid;
     arg->handle_bufioreq = handle_bufioreq;
 
-    rc = do_xen_hypercall(xch, &hypercall);
+    rc = xencall2(xch->xcall, __HYPERVISOR_hvm_op,
+                  HVMOP_create_ioreq_server,
+                  HYPERCALL_BUFFER_AS_ARG(arg));
 
     *id = arg->id;
 
@@ -1428,7 +1416,6 @@ int xc_hvm_get_ioreq_server_info(xc_interface *xch,
                                  xen_pfn_t *bufioreq_pfn,
                                  evtchn_port_t *bufioreq_port)
 {
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(xen_hvm_get_ioreq_server_info_t, arg);
     int rc;
 
@@ -1436,14 +1423,12 @@ int xc_hvm_get_ioreq_server_info(xc_interface *xch,
     if ( arg == NULL )
         return -1;
 
-    hypercall.op     = __HYPERVISOR_hvm_op;
-    hypercall.arg[0] = HVMOP_get_ioreq_server_info;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
-
     arg->domid = domid;
     arg->id = id;
 
-    rc = do_xen_hypercall(xch, &hypercall);
+    rc = xencall2(xch->xcall, __HYPERVISOR_hvm_op,
+                  HVMOP_get_ioreq_server_info,
+                  HYPERCALL_BUFFER_AS_ARG(arg));
     if ( rc != 0 )
         goto done;
 
@@ -1465,7 +1450,6 @@ int xc_hvm_map_io_range_to_ioreq_server(xc_interface *xch, domid_t domid,
                                         ioservid_t id, int is_mmio,
                                         uint64_t start, uint64_t end)
 {
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(xen_hvm_io_range_t, arg);
     int rc;
 
@@ -1473,17 +1457,15 @@ int xc_hvm_map_io_range_to_ioreq_server(xc_interface *xch, domid_t domid,
     if ( arg == NULL )
         return -1;
 
-    hypercall.op     = __HYPERVISOR_hvm_op;
-    hypercall.arg[0] = HVMOP_map_io_range_to_ioreq_server;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
-
     arg->domid = domid;
     arg->id = id;
     arg->type = is_mmio ? HVMOP_IO_RANGE_MEMORY : HVMOP_IO_RANGE_PORT;
     arg->start = start;
     arg->end = end;
 
-    rc = do_xen_hypercall(xch, &hypercall);
+    rc = xencall2(xch->xcall, __HYPERVISOR_hvm_op,
+                  HVMOP_map_io_range_to_ioreq_server,
+                  HYPERCALL_BUFFER_AS_ARG(arg));
 
     xc_hypercall_buffer_free(xch, arg);
     return rc;
@@ -1493,7 +1475,6 @@ int xc_hvm_unmap_io_range_from_ioreq_server(xc_interface *xch, domid_t domid,
                                             ioservid_t id, int is_mmio,
                                             uint64_t start, uint64_t end)
 {
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(xen_hvm_io_range_t, arg);
     int rc;
 
@@ -1501,17 +1482,15 @@ int xc_hvm_unmap_io_range_from_ioreq_server(xc_interface *xch, domid_t domid,
     if ( arg == NULL )
         return -1;
 
-    hypercall.op     = __HYPERVISOR_hvm_op;
-    hypercall.arg[0] = HVMOP_unmap_io_range_from_ioreq_server;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
-
     arg->domid = domid;
     arg->id = id;
     arg->type = is_mmio ? HVMOP_IO_RANGE_MEMORY : HVMOP_IO_RANGE_PORT;
     arg->start = start;
     arg->end = end;
 
-    rc = do_xen_hypercall(xch, &hypercall);
+    rc = xencall2(xch->xcall, __HYPERVISOR_hvm_op,
+                  HVMOP_unmap_io_range_from_ioreq_server,
+                  HYPERCALL_BUFFER_AS_ARG(arg));
 
     xc_hypercall_buffer_free(xch, arg);
     return rc;
@@ -1522,7 +1501,6 @@ int xc_hvm_map_pcidev_to_ioreq_server(xc_interface *xch, domid_t domid,
                                       uint8_t bus, uint8_t device,
                                       uint8_t function)
 {
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(xen_hvm_io_range_t, arg);
     int rc;
 
@@ -1535,10 +1513,6 @@ int xc_hvm_map_pcidev_to_ioreq_server(xc_interface *xch, domid_t domid,
     if ( arg == NULL )
         return -1;
 
-    hypercall.op     = __HYPERVISOR_hvm_op;
-    hypercall.arg[0] = HVMOP_map_io_range_to_ioreq_server;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
-
     arg->domid = domid;
     arg->id = id;
     arg->type = HVMOP_IO_RANGE_PCI;
@@ -1552,7 +1526,9 @@ int xc_hvm_map_pcidev_to_ioreq_server(xc_interface *xch, domid_t domid,
                                            (uint64_t)device,
                                            (uint64_t)function);
 
-    rc = do_xen_hypercall(xch, &hypercall);
+    rc = xencall2(xch->xcall, __HYPERVISOR_hvm_op,
+                  HVMOP_map_io_range_to_ioreq_server,
+                  HYPERCALL_BUFFER_AS_ARG(arg));
 
     xc_hypercall_buffer_free(xch, arg);
     return rc;
@@ -1563,7 +1539,6 @@ int xc_hvm_unmap_pcidev_from_ioreq_server(xc_interface *xch, domid_t domid,
                                           uint8_t bus, uint8_t device,
                                           uint8_t function)
 {
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(xen_hvm_io_range_t, arg);
     int rc;
 
@@ -1576,10 +1551,6 @@ int xc_hvm_unmap_pcidev_from_ioreq_server(xc_interface *xch, domid_t domid,
     if ( arg == NULL )
         return -1;
 
-    hypercall.op     = __HYPERVISOR_hvm_op;
-    hypercall.arg[0] = HVMOP_unmap_io_range_from_ioreq_server;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
-
     arg->domid = domid;
     arg->id = id;
     arg->type = HVMOP_IO_RANGE_PCI;
@@ -1588,7 +1559,9 @@ int xc_hvm_unmap_pcidev_from_ioreq_server(xc_interface *xch, domid_t domid,
                                            (uint64_t)device,
                                            (uint64_t)function);
 
-    rc = do_xen_hypercall(xch, &hypercall);
+    rc = xencall2(xch->xcall, __HYPERVISOR_hvm_op,
+                  HVMOP_unmap_io_range_from_ioreq_server,
+                  HYPERCALL_BUFFER_AS_ARG(arg));
 
     xc_hypercall_buffer_free(xch, arg);
     return rc;
@@ -1598,7 +1571,6 @@ int xc_hvm_destroy_ioreq_server(xc_interface *xch,
                                 domid_t domid,
                                 ioservid_t id)
 {
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(xen_hvm_destroy_ioreq_server_t, arg);
     int rc;
 
@@ -1606,14 +1578,12 @@ int xc_hvm_destroy_ioreq_server(xc_interface *xch,
     if ( arg == NULL )
         return -1;
 
-    hypercall.op     = __HYPERVISOR_hvm_op;
-    hypercall.arg[0] = HVMOP_destroy_ioreq_server;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
-
     arg->domid = domid;
     arg->id = id;
 
-    rc = do_xen_hypercall(xch, &hypercall);
+    rc = xencall2(xch->xcall, __HYPERVISOR_hvm_op,
+                  HVMOP_destroy_ioreq_server,
+                  HYPERCALL_BUFFER_AS_ARG(arg));
 
     xc_hypercall_buffer_free(xch, arg);
     return rc;
@@ -1624,7 +1594,6 @@ int xc_hvm_set_ioreq_server_state(xc_interface *xch,
                                   ioservid_t id,
                                   int enabled)
 {
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(xen_hvm_set_ioreq_server_state_t, arg);
     int rc;
 
@@ -1632,15 +1601,13 @@ int xc_hvm_set_ioreq_server_state(xc_interface *xch,
     if ( arg == NULL )
         return -1;
 
-    hypercall.op     = __HYPERVISOR_hvm_op;
-    hypercall.arg[0] = HVMOP_set_ioreq_server_state;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
-
     arg->domid = domid;
     arg->id = id;
     arg->enabled = !!enabled;
 
-    rc = do_xen_hypercall(xch, &hypercall);
+    rc = xencall2(xch->xcall, __HYPERVISOR_hvm_op,
+                  HVMOP_set_ioreq_server_state,
+                  HYPERCALL_BUFFER_AS_ARG(arg));
 
     xc_hypercall_buffer_free(xch, arg);
     return rc;
diff --git a/tools/libxc/xc_evtchn.c b/tools/libxc/xc_evtchn.c
index e6bd25c..59ba6c9 100644
--- a/tools/libxc/xc_evtchn.c
+++ b/tools/libxc/xc_evtchn.c
@@ -26,7 +26,6 @@ static int do_evtchn_op(xc_interface *xch, int cmd, void *arg,
                         size_t arg_size, int silently_fail)
 {
     int ret = -1;
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BOUNCE(arg, arg_size, XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
 
     if ( xc_hypercall_bounce_pre(xch, arg) )
@@ -35,11 +34,9 @@ static int do_evtchn_op(xc_interface *xch, int cmd, void *arg,
         goto out;
     }
 
-    hypercall.op     = __HYPERVISOR_event_channel_op;
-    hypercall.arg[0] = cmd;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
-
-    if ((ret = do_xen_hypercall(xch, &hypercall)) < 0 && !silently_fail)
+    ret = xencall2(xch->xcall, __HYPERVISOR_event_channel_op,
+                   cmd, HYPERCALL_BUFFER_AS_ARG(arg));
+    if ( ret < 0 && !silently_fail )
         ERROR("do_evtchn_op: HYPERVISOR_event_channel_op failed: %d", ret);
 
     xc_hypercall_bounce_post(xch, arg);
diff --git a/tools/libxc/xc_flask.c b/tools/libxc/xc_flask.c
index e24a2e7..07298a8 100644
--- a/tools/libxc/xc_flask.c
+++ b/tools/libxc/xc_flask.c
@@ -38,7 +38,6 @@
 int xc_flask_op(xc_interface *xch, xen_flask_op_t *op)
 {
     int ret = -1;
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BOUNCE(op, sizeof(*op), XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
 
     op->interface_version = XEN_FLASK_INTERFACE_VERSION;
@@ -49,10 +48,9 @@ int xc_flask_op(xc_interface *xch, xen_flask_op_t *op)
         goto out;
     }
 
-    hypercall.op     = __HYPERVISOR_xsm_op;
-    hypercall.arg[0] = HYPERCALL_BUFFER_AS_ARG(op);
-
-    if ( (ret = do_xen_hypercall(xch, &hypercall)) < 0 )
+    ret = xencall1(xch->xcall, __HYPERVISOR_xsm_op,
+                   HYPERCALL_BUFFER_AS_ARG(op));
+    if ( ret < 0 )
     {
         if ( errno == EACCES )
             fprintf(stderr, "XSM operation failed!\n");
diff --git a/tools/libxc/xc_freebsd_osdep.c b/tools/libxc/xc_freebsd_osdep.c
index 4c0e2fd..b0ec965 100644
--- a/tools/libxc/xc_freebsd_osdep.c
+++ b/tools/libxc/xc_freebsd_osdep.c
@@ -89,53 +89,6 @@ int osdep_privcmd_close(xc_interface *xch)
     return close(fd);
 }
 
-/*------------------------ Privcmd hypercall interface -----------------------*/
-void *osdep_alloc_hypercall_buffer(xc_interface *xch, int npages)
-{
-    size_t size = npages * XC_PAGE_SIZE;
-    void *p;
-
-    /* Address returned by mmap is page aligned. */
-    p = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS,
-             -1, 0);
-    if (p == NULL)
-        return NULL;
-
-    /*
-     * Since FreeBSD doesn't have the MAP_LOCKED flag,
-     * lock memory using mlock.
-     */
-    if ( mlock(p, size) < 0 )
-    {
-        munmap(p, size);
-        return NULL;
-    }
-
-    return p;
-}
-
-void osdep_free_hypercall_buffer(xc_interface *xch, void *ptr, int npages)
-{
-
-    int saved_errno = errno;
-    /* Unlock pages */
-    munlock(ptr, npages * XC_PAGE_SIZE);
-
-    munmap(ptr, npages * XC_PAGE_SIZE);
-    /* We MUST propagate the hypercall errno, not unmap call's. */
-    errno = saved_errno;
-}
-
-int do_xen_hypercall(xc_interface *xch, privcmd_hypercall_t *hypercall)
-{
-    int fd = xch->privcmdfd;
-    int ret;
-
-    ret = ioctl(fd, IOCTL_PRIVCMD_HYPERCALL, hypercall);
-
-    return (ret == 0) ? hypercall->retval : ret;
-}
-
 /*----------------------- Privcmd foreign map interface ----------------------*/
 void *xc_map_foreign_bulk(xc_interface *xch,
                           uint32_t dom, int prot,
diff --git a/tools/libxc/xc_gnttab.c b/tools/libxc/xc_gnttab.c
index 8c7e906..3ee91bc 100644
--- a/tools/libxc/xc_gnttab.c
+++ b/tools/libxc/xc_gnttab.c
@@ -22,7 +22,6 @@
 int xc_gnttab_op(xc_interface *xch, int cmd, void * op, int op_size, int count)
 {
     int ret = 0;
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BOUNCE(op, count * op_size, XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
 
     if ( xc_hypercall_bounce_pre(xch, op) )
@@ -31,12 +30,8 @@ int xc_gnttab_op(xc_interface *xch, int cmd, void * op, int op_size, int count)
         goto out1;
     }
 
-    hypercall.op = __HYPERVISOR_grant_table_op;
-    hypercall.arg[0] = cmd;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(op);
-    hypercall.arg[2] = count;
-
-    ret = do_xen_hypercall(xch, &hypercall);
+    ret = xencall3(xch->xcall,  __HYPERVISOR_grant_table_op,
+                   cmd, HYPERCALL_BUFFER_AS_ARG(op), count);
 
     xc_hypercall_bounce_post(xch, op);
 
diff --git a/tools/libxc/xc_hcall_buf.c b/tools/libxc/xc_hcall_buf.c
index ab8bee5..b70b692 100644
--- a/tools/libxc/xc_hcall_buf.c
+++ b/tools/libxc/xc_hcall_buf.c
@@ -18,7 +18,6 @@
 
 #include <stdlib.h>
 #include <string.h>
-#include <pthread.h>
 
 #include "xc_private.h"
 #include "xg_private.h"
@@ -29,163 +28,38 @@ xc_hypercall_buffer_t XC__HYPERCALL_BUFFER_NAME(HYPERCALL_BUFFER_NULL) = {
     HYPERCALL_BUFFER_INIT_NO_BOUNCE
 };
 
-pthread_mutex_t hypercall_buffer_cache_mutex = PTHREAD_MUTEX_INITIALIZER;
-
-static void hypercall_buffer_cache_lock(xc_interface *xch)
-{
-    int saved_errno = errno;
-    if ( xch->flags & XC_OPENFLAG_NON_REENTRANT )
-        return;
-    pthread_mutex_lock(&hypercall_buffer_cache_mutex);
-    /* Ignore pthread errors. */
-    errno = saved_errno;
-}
-
-static void hypercall_buffer_cache_unlock(xc_interface *xch)
-{
-    int saved_errno = errno;
-    if ( xch->flags & XC_OPENFLAG_NON_REENTRANT )
-        return;
-    pthread_mutex_unlock(&hypercall_buffer_cache_mutex);
-    /* Ignore pthread errors. */
-    errno = saved_errno;
-}
-
-static void *hypercall_buffer_cache_alloc(xc_interface *xch, int nr_pages)
-{
-    void *p = NULL;
-
-    hypercall_buffer_cache_lock(xch);
-
-    xch->hypercall_buffer_total_allocations++;
-    xch->hypercall_buffer_current_allocations++;
-    if ( xch->hypercall_buffer_current_allocations > xch->hypercall_buffer_maximum_allocations )
-        xch->hypercall_buffer_maximum_allocations = xch->hypercall_buffer_current_allocations;
-
-    if ( nr_pages > 1 )
-    {
-        xch->hypercall_buffer_cache_toobig++;
-    }
-    else if ( xch->hypercall_buffer_cache_nr > 0 )
-    {
-        p = xch->hypercall_buffer_cache[--xch->hypercall_buffer_cache_nr];
-        xch->hypercall_buffer_cache_hits++;
-    }
-    else
-    {
-        xch->hypercall_buffer_cache_misses++;
-    }
-
-    hypercall_buffer_cache_unlock(xch);
-
-    return p;
-}
-
-static int hypercall_buffer_cache_free(xc_interface *xch, void *p, int nr_pages)
-{
-    int rc = 0;
-
-    hypercall_buffer_cache_lock(xch);
-
-    xch->hypercall_buffer_total_releases++;
-    xch->hypercall_buffer_current_allocations--;
-
-    if ( nr_pages == 1 && xch->hypercall_buffer_cache_nr < HYPERCALL_BUFFER_CACHE_SIZE )
-    {
-        xch->hypercall_buffer_cache[xch->hypercall_buffer_cache_nr++] = p;
-        rc = 1;
-    }
-
-    hypercall_buffer_cache_unlock(xch);
-
-    return rc;
-}
-
-void xc__hypercall_buffer_cache_release(xc_interface *xch)
-{
-    void *p;
-
-    hypercall_buffer_cache_lock(xch);
-
-    DBGPRINTF("hypercall buffer: total allocations:%d total releases:%d",
-              xch->hypercall_buffer_total_allocations,
-              xch->hypercall_buffer_total_releases);
-    DBGPRINTF("hypercall buffer: current allocations:%d maximum allocations:%d",
-              xch->hypercall_buffer_current_allocations,
-              xch->hypercall_buffer_maximum_allocations);
-    DBGPRINTF("hypercall buffer: cache current size:%d",
-              xch->hypercall_buffer_cache_nr);
-    DBGPRINTF("hypercall buffer: cache hits:%d misses:%d toobig:%d",
-              xch->hypercall_buffer_cache_hits,
-              xch->hypercall_buffer_cache_misses,
-              xch->hypercall_buffer_cache_toobig);
-
-    while ( xch->hypercall_buffer_cache_nr > 0 )
-    {
-        p = xch->hypercall_buffer_cache[--xch->hypercall_buffer_cache_nr];
-        osdep_free_hypercall_buffer(xch, p, 1);
-    }
-
-    hypercall_buffer_cache_unlock(xch);
-}
-
 void *xc__hypercall_buffer_alloc_pages(xc_interface *xch, xc_hypercall_buffer_t *b, int nr_pages)
 {
-    void *p = hypercall_buffer_cache_alloc(xch, nr_pages);
-
-    if ( !p )
-        p = osdep_alloc_hypercall_buffer(xch, nr_pages);
+    void *p = xencall_alloc_buffer_pages(xch->xcall, nr_pages);
 
     if (!p)
         return NULL;
 
     b->hbuf = p;
 
-    memset(p, 0, nr_pages * PAGE_SIZE);
-
     return b->hbuf;
 }
 
 void xc__hypercall_buffer_free_pages(xc_interface *xch, xc_hypercall_buffer_t *b, int nr_pages)
 {
-    if ( b->hbuf == NULL )
-        return;
-
-    if ( !hypercall_buffer_cache_free(xch, b->hbuf, nr_pages) )
-        osdep_free_hypercall_buffer(xch, b->hbuf, nr_pages);
+    xencall_free_buffer_pages(xch->xcall, b->hbuf, nr_pages);
 }
 
-struct allocation_header {
-    int nr_pages;
-};
-
 void *xc__hypercall_buffer_alloc(xc_interface *xch, xc_hypercall_buffer_t *b, size_t size)
 {
-    size_t actual_size = ROUNDUP(size + sizeof(struct allocation_header), PAGE_SHIFT);
-    int nr_pages = actual_size >> PAGE_SHIFT;
-    struct allocation_header *hdr;
+    void *p = xencall_alloc_buffer(xch->xcall, size);
 
-    hdr = xc__hypercall_buffer_alloc_pages(xch, b, nr_pages);
-    if ( hdr == NULL )
+    if (!p)
         return NULL;
 
-    b->hbuf = (void *)(hdr+1);
+    b->hbuf = p;
 
-    hdr->nr_pages = nr_pages;
     return b->hbuf;
 }
 
 void xc__hypercall_buffer_free(xc_interface *xch, xc_hypercall_buffer_t *b)
 {
-    struct allocation_header *hdr;
-
-    if (b->hbuf == NULL)
-        return;
-
-    hdr = b->hbuf;
-    b->hbuf = --hdr;
-
-    xc__hypercall_buffer_free_pages(xch, b, hdr->nr_pages);
+    xencall_free_buffer(xch->xcall, b->hbuf);
 }
 
 int xc__hypercall_bounce_pre(xc_interface *xch, xc_hypercall_buffer_t *b)
diff --git a/tools/libxc/xc_kexec.c b/tools/libxc/xc_kexec.c
index a49cffb..1cceb5d 100644
--- a/tools/libxc/xc_kexec.c
+++ b/tools/libxc/xc_kexec.c
@@ -14,7 +14,6 @@
 
 int xc_kexec_exec(xc_interface *xch, int type)
 {
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(xen_kexec_exec_t, exec);
     int ret = -1;
 
@@ -27,11 +26,9 @@ int xc_kexec_exec(xc_interface *xch, int type)
 
     exec->type = type;
 
-    hypercall.op = __HYPERVISOR_kexec_op;
-    hypercall.arg[0] = KEXEC_CMD_kexec;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(exec);
-
-    ret = do_xen_hypercall(xch, &hypercall);
+    ret = xencall2(xch->xcall, __HYPERVISOR_kexec_op,
+		   KEXEC_CMD_kexec,
+		   HYPERCALL_BUFFER_AS_ARG(exec));
 
 out:
     xc_hypercall_buffer_free(xch, exec);
@@ -42,7 +39,6 @@ out:
 int xc_kexec_get_range(xc_interface *xch, int range,  int nr,
                        uint64_t *size, uint64_t *start)
 {
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(xen_kexec_range_t, get_range);
     int ret = -1;
 
@@ -56,11 +52,9 @@ int xc_kexec_get_range(xc_interface *xch, int range,  int nr,
     get_range->range = range;
     get_range->nr = nr;
 
-    hypercall.op = __HYPERVISOR_kexec_op;
-    hypercall.arg[0] = KEXEC_CMD_kexec_get_range;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(get_range);
-
-    ret = do_xen_hypercall(xch, &hypercall);
+    ret = xencall2(xch->xcall, __HYPERVISOR_kexec_op,
+		   KEXEC_CMD_kexec_get_range,
+		   HYPERCALL_BUFFER_AS_ARG(get_range));
 
     *size = get_range->size;
     *start = get_range->start;
@@ -76,7 +70,6 @@ int xc_kexec_load(xc_interface *xch, uint8_t type, uint16_t arch,
                   uint32_t nr_segments, xen_kexec_segment_t *segments)
 {
     int ret = -1;
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BOUNCE(segments, sizeof(*segments) * nr_segments,
                              XC_HYPERCALL_BUFFER_BOUNCE_IN);
     DECLARE_HYPERCALL_BUFFER(xen_kexec_load_t, load);
@@ -99,11 +92,9 @@ int xc_kexec_load(xc_interface *xch, uint8_t type, uint16_t arch,
     load->nr_segments = nr_segments;
     set_xen_guest_handle(load->segments.h, segments);
 
-    hypercall.op = __HYPERVISOR_kexec_op;
-    hypercall.arg[0] = KEXEC_CMD_kexec_load;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(load);
-
-    ret = do_xen_hypercall(xch, &hypercall);
+    ret = xencall2(xch->xcall, __HYPERVISOR_kexec_op,
+		   KEXEC_CMD_kexec_load,
+		   HYPERCALL_BUFFER_AS_ARG(load));
 
 out:
     xc_hypercall_buffer_free(xch, load);
@@ -114,7 +105,6 @@ out:
 
 int xc_kexec_unload(xc_interface *xch, int type)
 {
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(xen_kexec_unload_t, unload);
     int ret = -1;
 
@@ -127,11 +117,9 @@ int xc_kexec_unload(xc_interface *xch, int type)
 
     unload->type = type;
 
-    hypercall.op = __HYPERVISOR_kexec_op;
-    hypercall.arg[0] = KEXEC_CMD_kexec_unload;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(unload);
-
-    ret = do_xen_hypercall(xch, &hypercall);
+    ret = xencall2(xch->xcall, __HYPERVISOR_kexec_op,
+		   KEXEC_CMD_kexec_unload,
+		   HYPERCALL_BUFFER_AS_ARG(unload));
 
 out:
     xc_hypercall_buffer_free(xch, unload);
diff --git a/tools/libxc/xc_linux_osdep.c b/tools/libxc/xc_linux_osdep.c
index d17a52b..488e8df 100644
--- a/tools/libxc/xc_linux_osdep.c
+++ b/tools/libxc/xc_linux_osdep.c
@@ -86,55 +86,6 @@ int osdep_privcmd_close(xc_interface *xch)
     return close(fd);
 }
 
-void *osdep_alloc_hypercall_buffer(xc_interface *xch, int npages)
-{
-    size_t size = npages * XC_PAGE_SIZE;
-    void *p;
-    int rc, saved_errno;
-
-    /* Address returned by mmap is page aligned. */
-    p = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_LOCKED, -1, 0);
-    if ( p == MAP_FAILED )
-    {
-        PERROR("xc_alloc_hypercall_buffer: mmap failed");
-        return NULL;
-    }
-
-    /* Do not copy the VMA to child process on fork. Avoid the page being COW
-        on hypercall. */
-    rc = madvise(p, npages * XC_PAGE_SIZE, MADV_DONTFORK);
-    if ( rc < 0 )
-    {
-        PERROR("xc_alloc_hypercall_buffer: madvise failed");
-        goto out;
-    }
-
-    return p;
-
-out:
-    saved_errno = errno;
-    (void)munmap(p, size);
-    errno = saved_errno;
-    return NULL;
-}
-
-void osdep_free_hypercall_buffer(xc_interface *xch, void *ptr, int npages)
-{
-    int saved_errno = errno;
-    /* Recover the VMA flags. Maybe it's not necessary */
-    madvise(ptr, npages * XC_PAGE_SIZE, MADV_DOFORK);
-
-    munmap(ptr, npages * XC_PAGE_SIZE);
-    /* We MUST propagate the hypercall errno, not unmap call's. */
-    errno = saved_errno;
-}
-
-int do_xen_hypercall(xc_interface *xch, privcmd_hypercall_t *hypercall)
-{
-    int fd = xch->privcmdfd;
-    return ioctl(fd, IOCTL_PRIVCMD_HYPERCALL, hypercall);
-}
-
 static int xc_map_foreign_batch_single(int fd, uint32_t dom,
                                        xen_pfn_t *mfn, unsigned long addr)
 {
diff --git a/tools/libxc/xc_minios.c b/tools/libxc/xc_minios.c
index 0a2ac5c..27a4c4a 100644
--- a/tools/libxc/xc_minios.c
+++ b/tools/libxc/xc_minios.c
@@ -62,38 +62,6 @@ void minios_interface_close_fd(int fd)
     files[fd].type = FTYPE_NONE;
 }
 
-void *osdep_alloc_hypercall_buffer(xc_interface *xch, int npages)
-{
-    return xc_memalign(xch, PAGE_SIZE, npages * PAGE_SIZE);
-}
-
-void osdep_free_hypercall_buffer(xc_interface *xch, void *ptr, int npages)
-{
-    free(ptr);
-}
-
-int do_xen_hypercall(xc_interface *xch, privcmd_hypercall_t *hypercall)
-{
-    multicall_entry_t call;
-    int i, ret;
-
-    call.op = hypercall->op;
-    for (i = 0; i < ARRAY_SIZE(hypercall->arg); i++)
-	call.args[i] = hypercall->arg[i];
-
-    ret = HYPERVISOR_multicall(&call, 1);
-
-    if (ret < 0) {
-	errno = -ret;
-	return -1;
-    }
-    if ((long) call.result < 0) {
-        errno = - (long) call.result;
-        return -1;
-    }
-    return call.result;
-}
-
 void *xc_map_foreign_bulk(xc_interface *xch,
                           uint32_t dom, int prot,
                           const xen_pfn_t *arr, int *err, unsigned int num)
diff --git a/tools/libxc/xc_misc.c b/tools/libxc/xc_misc.c
index b827bbb..fb9f628 100644
--- a/tools/libxc/xc_misc.c
+++ b/tools/libxc/xc_misc.c
@@ -324,7 +324,6 @@ int xc_sched_id(xc_interface *xch,
 int xc_mca_op(xc_interface *xch, struct xen_mc *mc)
 {
     int ret = 0;
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BOUNCE(mc, sizeof(*mc), XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
 
     if ( xc_hypercall_bounce_pre(xch, mc) )
@@ -334,9 +333,9 @@ int xc_mca_op(xc_interface *xch, struct xen_mc *mc)
     }
     mc->interface_version = XEN_MCA_INTERFACE_VERSION;
 
-    hypercall.op = __HYPERVISOR_mca;
-    hypercall.arg[0] = HYPERCALL_BUFFER_AS_ARG(mc);
-    ret = do_xen_hypercall(xch, &hypercall);
+    ret = xencall1(xch->xcall, __HYPERVISOR_mca,
+                   HYPERCALL_BUFFER_AS_ARG(mc));
+
     xc_hypercall_bounce_post(xch, mc);
     return ret;
 }
@@ -472,7 +471,6 @@ int xc_hvm_set_pci_intx_level(
     uint8_t domain, uint8_t bus, uint8_t device, uint8_t intx,
     unsigned int level)
 {
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(struct xen_hvm_set_pci_intx_level, arg);
     int rc;
 
@@ -483,10 +481,6 @@ int xc_hvm_set_pci_intx_level(
         return -1;
     }
 
-    hypercall.op     = __HYPERVISOR_hvm_op;
-    hypercall.arg[0] = HVMOP_set_pci_intx_level;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
-
     arg->domid  = dom;
     arg->domain = domain;
     arg->bus    = bus;
@@ -494,7 +488,9 @@ int xc_hvm_set_pci_intx_level(
     arg->intx   = intx;
     arg->level  = level;
 
-    rc = do_xen_hypercall(xch, &hypercall);
+    rc = xencall2(xch->xcall, __HYPERVISOR_hvm_op,
+                  HVMOP_set_pci_intx_level,
+                  HYPERCALL_BUFFER_AS_ARG(arg));
 
     xc_hypercall_buffer_free(xch, arg);
 
@@ -506,7 +502,6 @@ int xc_hvm_set_isa_irq_level(
     uint8_t isa_irq,
     unsigned int level)
 {
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(struct xen_hvm_set_isa_irq_level, arg);
     int rc;
 
@@ -517,15 +512,13 @@ int xc_hvm_set_isa_irq_level(
         return -1;
     }
 
-    hypercall.op     = __HYPERVISOR_hvm_op;
-    hypercall.arg[0] = HVMOP_set_isa_irq_level;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
-
     arg->domid   = dom;
     arg->isa_irq = isa_irq;
     arg->level   = level;
 
-    rc = do_xen_hypercall(xch, &hypercall);
+    rc = xencall2(xch->xcall, __HYPERVISOR_hvm_op,
+                  HVMOP_set_isa_irq_level,
+                  HYPERCALL_BUFFER_AS_ARG(arg));
 
     xc_hypercall_buffer_free(xch, arg);
 
@@ -535,7 +528,6 @@ int xc_hvm_set_isa_irq_level(
 int xc_hvm_set_pci_link_route(
     xc_interface *xch, domid_t dom, uint8_t link, uint8_t isa_irq)
 {
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(struct xen_hvm_set_pci_link_route, arg);
     int rc;
 
@@ -546,15 +538,13 @@ int xc_hvm_set_pci_link_route(
         return -1;
     }
 
-    hypercall.op     = __HYPERVISOR_hvm_op;
-    hypercall.arg[0] = HVMOP_set_pci_link_route;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
-
     arg->domid   = dom;
     arg->link    = link;
     arg->isa_irq = isa_irq;
 
-    rc = do_xen_hypercall(xch, &hypercall);
+    rc = xencall2(xch->xcall, __HYPERVISOR_hvm_op,
+                  HVMOP_set_pci_link_route,
+                  HYPERCALL_BUFFER_AS_ARG(arg));
 
     xc_hypercall_buffer_free(xch, arg);
 
@@ -564,7 +554,6 @@ int xc_hvm_set_pci_link_route(
 int xc_hvm_inject_msi(
     xc_interface *xch, domid_t dom, uint64_t addr, uint32_t data)
 {
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(struct xen_hvm_inject_msi, arg);
     int rc;
 
@@ -575,15 +564,13 @@ int xc_hvm_inject_msi(
         return -1;
     }
 
-    hypercall.op     = __HYPERVISOR_hvm_op;
-    hypercall.arg[0] = HVMOP_inject_msi;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
-
     arg->domid = dom;
     arg->addr  = addr;
     arg->data  = data;
 
-    rc = do_xen_hypercall(xch, &hypercall);
+    rc = xencall2(xch->xcall, __HYPERVISOR_hvm_op,
+                  HVMOP_inject_msi,
+                  HYPERCALL_BUFFER_AS_ARG(arg));
 
     xc_hypercall_buffer_free(xch, arg);
 
@@ -595,7 +582,6 @@ int xc_hvm_track_dirty_vram(
     uint64_t first_pfn, uint64_t nr,
     unsigned long *dirty_bitmap)
 {
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BOUNCE(dirty_bitmap, (nr+7) / 8, XC_HYPERCALL_BUFFER_BOUNCE_OUT);
     DECLARE_HYPERCALL_BUFFER(struct xen_hvm_track_dirty_vram, arg);
     int rc;
@@ -608,16 +594,14 @@ int xc_hvm_track_dirty_vram(
         goto out;
     }
 
-    hypercall.op     = __HYPERVISOR_hvm_op;
-    hypercall.arg[0] = HVMOP_track_dirty_vram;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
-
     arg->domid     = dom;
     arg->first_pfn = first_pfn;
     arg->nr        = nr;
     set_xen_guest_handle(arg->dirty_bitmap, dirty_bitmap);
 
-    rc = do_xen_hypercall(xch, &hypercall);
+    rc = xencall2(xch->xcall, __HYPERVISOR_hvm_op,
+                  HVMOP_track_dirty_vram,
+                  HYPERCALL_BUFFER_AS_ARG(arg));
 
 out:
     xc_hypercall_buffer_free(xch, arg);
@@ -628,7 +612,6 @@ out:
 int xc_hvm_modified_memory(
     xc_interface *xch, domid_t dom, uint64_t first_pfn, uint64_t nr)
 {
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(struct xen_hvm_modified_memory, arg);
     int rc;
 
@@ -639,15 +622,13 @@ int xc_hvm_modified_memory(
         return -1;
     }
 
-    hypercall.op     = __HYPERVISOR_hvm_op;
-    hypercall.arg[0] = HVMOP_modified_memory;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
-
     arg->domid     = dom;
     arg->first_pfn = first_pfn;
     arg->nr        = nr;
 
-    rc = do_xen_hypercall(xch, &hypercall);
+    rc = xencall2(xch->xcall, __HYPERVISOR_hvm_op,
+                  HVMOP_modified_memory,
+                  HYPERCALL_BUFFER_AS_ARG(arg));
 
     xc_hypercall_buffer_free(xch, arg);
 
@@ -657,7 +638,6 @@ int xc_hvm_modified_memory(
 int xc_hvm_set_mem_type(
     xc_interface *xch, domid_t dom, hvmmem_type_t mem_type, uint64_t first_pfn, uint64_t nr)
 {
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(struct xen_hvm_set_mem_type, arg);
     int rc;
 
@@ -673,11 +653,9 @@ int xc_hvm_set_mem_type(
     arg->first_pfn    = first_pfn;
     arg->nr           = nr;
 
-    hypercall.op     = __HYPERVISOR_hvm_op;
-    hypercall.arg[0] = HVMOP_set_mem_type;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
-
-    rc = do_xen_hypercall(xch, &hypercall);
+    rc = xencall2(xch->xcall, __HYPERVISOR_hvm_op,
+                  HVMOP_set_mem_type,
+                  HYPERCALL_BUFFER_AS_ARG(arg));
 
     xc_hypercall_buffer_free(xch, arg);
 
@@ -689,7 +667,6 @@ int xc_hvm_inject_trap(
     uint32_t type, uint32_t error_code, uint32_t insn_len,
     uint64_t cr2)
 {
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(struct xen_hvm_inject_trap, arg);
     int rc;
 
@@ -708,11 +685,9 @@ int xc_hvm_inject_trap(
     arg->insn_len    = insn_len;
     arg->cr2         = cr2;
 
-    hypercall.op     = __HYPERVISOR_hvm_op;
-    hypercall.arg[0] = HVMOP_inject_trap;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
-
-    rc = do_xen_hypercall(xch, &hypercall);
+    rc = xencall2(xch->xcall, __HYPERVISOR_hvm_op,
+                  HVMOP_inject_trap,
+                  HYPERCALL_BUFFER_AS_ARG(arg));
 
     xc_hypercall_buffer_free(xch, arg);
 
diff --git a/tools/libxc/xc_netbsd.c b/tools/libxc/xc_netbsd.c
index 5361f2b..78683a2 100644
--- a/tools/libxc/xc_netbsd.c
+++ b/tools/libxc/xc_netbsd.c
@@ -68,46 +68,6 @@ int osdep_privcmd_close(xc_interface *xch)
     return close(fd);
 }
 
-void *osdep_alloc_hypercall_buffer(xc_interface *xch, int npages)
-{
-    size_t size = npages * XC_PAGE_SIZE;
-    void *p;
-
-    p = xc_memalign(xch, XC_PAGE_SIZE, size);
-    if (!p)
-        return NULL;
-
-    if ( mlock(p, size) < 0 )
-    {
-        free(p);
-        return NULL;
-    }
-    return p;
-}
-
-void osdep_free_hypercall_buffer(xc_interface *xch, void *ptr, int npages)
-{
-    (void) munlock(ptr, npages * XC_PAGE_SIZE);
-    free(ptr);
-}
-
-int do_xen_hypercall(xc_interface *xch, privcmd_hypercall_t *hypercall)
-{
-    int fd = xch->privcmdfd;
-    int error = ioctl(fd, IOCTL_PRIVCMD_HYPERCALL, hypercall);
-
-    /*
-     * Since NetBSD ioctl can only return 0 on success or < 0 on
-     * error, if we want to return a value from ioctl we should
-     * do so by setting hypercall->retval, to mimic Linux ioctl
-     * implementation.
-     */
-    if (error < 0)
-        return error;
-    else
-        return hypercall->retval;
-}
-
 void *xc_map_foreign_bulk(xc_interface *xch,
                           uint32_t dom, int prot,
                           const xen_pfn_t *arr, int *err, unsigned int num)
diff --git a/tools/libxc/xc_private.c b/tools/libxc/xc_private.c
index c56d748..00f96ba 100644
--- a/tools/libxc/xc_private.c
+++ b/tools/libxc/xc_private.c
@@ -40,16 +40,6 @@ struct xc_interface_core *xc_interface_open(xentoollog_logger *logger,
     xch->error_handler   = logger;           xch->error_handler_tofree   = 0;
     xch->dombuild_logger = dombuild_logger;  xch->dombuild_logger_tofree = 0;
 
-    xch->hypercall_buffer_cache_nr = 0;
-
-    xch->hypercall_buffer_total_allocations = 0;
-    xch->hypercall_buffer_total_releases = 0;
-    xch->hypercall_buffer_current_allocations = 0;
-    xch->hypercall_buffer_maximum_allocations = 0;
-    xch->hypercall_buffer_cache_hits = 0;
-    xch->hypercall_buffer_cache_misses = 0;
-    xch->hypercall_buffer_cache_toobig = 0;
-
     if (!xch->error_handler) {
         xch->error_handler = xch->error_handler_tofree =
             (xentoollog_logger*)
@@ -66,14 +56,22 @@ struct xc_interface_core *xc_interface_open(xentoollog_logger *logger,
     }
     *xch = xch_buf;
 
-    if (!(open_flags & XC_OPENFLAG_DUMMY)) {
-        if ( osdep_privcmd_open(xch) < 0 )
-            goto err;
-    }
+    if (open_flags & XC_OPENFLAG_DUMMY)
+        return xch; /* We are done */
+
+    if ( osdep_privcmd_open(xch) < 0 )
+        goto err;
+
+    xch->xcall = xencall_open(xch->error_handler,
+        open_flags & XC_OPENFLAG_NON_REENTRANT ? XENCALL_OPENFLAG_NON_REENTRANT : 0U);
+
+    if ( xch->xcall == NULL )
+        goto err;
 
     return xch;
 
  err:
+    osdep_privcmd_close(xch);
     xtl_logger_destroy(xch->error_handler_tofree);
     if (xch != &xch_buf) free(xch);
     return NULL;
@@ -86,11 +84,12 @@ int xc_interface_close(xc_interface *xch)
     if (!xch)
         return 0;
 
+    rc = xencall_close(xch->xcall);
+    if (rc) PERROR("Could not close xencall interface");
+
     rc = osdep_privcmd_close(xch);
     if (rc) PERROR("Could not close hypervisor interface");
 
-    xc__hypercall_buffer_cache_release(xch);
-
     xtl_logger_destroy(xch->dombuild_logger_tofree);
     xtl_logger_destroy(xch->error_handler_tofree);
 
@@ -229,7 +228,6 @@ int xc_mmuext_op(
     unsigned int nr_ops,
     domid_t dom)
 {
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BOUNCE(op, nr_ops*sizeof(*op), XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
     long ret = -1;
 
@@ -239,13 +237,9 @@ int xc_mmuext_op(
         goto out1;
     }
 
-    hypercall.op     = __HYPERVISOR_mmuext_op;
-    hypercall.arg[0] = HYPERCALL_BUFFER_AS_ARG(op);
-    hypercall.arg[1] = (unsigned long)nr_ops;
-    hypercall.arg[2] = (unsigned long)0;
-    hypercall.arg[3] = (unsigned long)dom;
-
-    ret = do_xen_hypercall(xch, &hypercall);
+    ret = xencall4(xch->xcall, __HYPERVISOR_mmuext_op,
+                   HYPERCALL_BUFFER_AS_ARG(op),
+                   nr_ops, 0, dom);
 
     xc_hypercall_bounce_post(xch, op);
 
@@ -255,8 +249,7 @@ int xc_mmuext_op(
 
 static int flush_mmu_updates(xc_interface *xch, struct xc_mmu *mmu)
 {
-    int err = 0;
-    DECLARE_HYPERCALL;
+    int rc, err = 0;
     DECLARE_NAMED_HYPERCALL_BOUNCE(updates, mmu->updates, mmu->idx*sizeof(*mmu->updates), XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
 
     if ( mmu->idx == 0 )
@@ -269,13 +262,10 @@ static int flush_mmu_updates(xc_interface *xch, struct xc_mmu *mmu)
         goto out;
     }
 
-    hypercall.op     = __HYPERVISOR_mmu_update;
-    hypercall.arg[0] = HYPERCALL_BUFFER_AS_ARG(updates);
-    hypercall.arg[1] = (unsigned long)mmu->idx;
-    hypercall.arg[2] = 0;
-    hypercall.arg[3] = mmu->subject;
-
-    if ( do_xen_hypercall(xch, &hypercall) < 0 )
+    rc = xencall4(xch->xcall, __HYPERVISOR_mmu_update,
+                  HYPERCALL_BUFFER_AS_ARG(updates),
+                  mmu->idx, 0, mmu->subject);
+    if ( rc < 0 )
     {
         ERROR("Failure when submitting mmu updates");
         err = 1;
@@ -318,7 +308,6 @@ int xc_flush_mmu_updates(xc_interface *xch, struct xc_mmu *mmu)
 
 int do_memory_op(xc_interface *xch, int cmd, void *arg, size_t len)
 {
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BOUNCE(arg, len, XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
     long ret = -1;
 
@@ -328,11 +317,8 @@ int do_memory_op(xc_interface *xch, int cmd, void *arg, size_t len)
         goto out1;
     }
 
-    hypercall.op     = __HYPERVISOR_memory_op;
-    hypercall.arg[0] = (unsigned long) cmd;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
-
-    ret = do_xen_hypercall(xch, &hypercall);
+    ret = xencall2(xch->xcall, __HYPERVISOR_memory_op,
+                   cmd, HYPERCALL_BUFFER_AS_ARG(arg));
 
     xc_hypercall_bounce_post(xch, arg);
  out1:
diff --git a/tools/libxc/xc_private.h b/tools/libxc/xc_private.h
index 408b1be..2288660 100644
--- a/tools/libxc/xc_private.h
+++ b/tools/libxc/xc_private.h
@@ -31,6 +31,7 @@
 
 #include "_paths.h"
 #include "xenctrl.h"
+#include <xencall.h>
 
 #include <xen/sys/privcmd.h>
 
@@ -54,7 +55,6 @@ struct iovec {
 #include <sys/uio.h>
 #endif
 
-#define DECLARE_HYPERCALL privcmd_hypercall_t hypercall
 #define DECLARE_DOMCTL struct xen_domctl domctl
 #define DECLARE_SYSCTL struct xen_sysctl sysctl
 #define DECLARE_PHYSDEV_OP struct physdev_op physdev_op
@@ -95,29 +95,11 @@ struct xc_interface_core {
     FILE *dombuild_logger_file;
     const char *currently_progress_reporting;
 
-    /*
-     * A simple cache of unused, single page, hypercall buffers
-     *
-     * Protected by a global lock.
-     */
-#define HYPERCALL_BUFFER_CACHE_SIZE 4
-    int hypercall_buffer_cache_nr;
-    void *hypercall_buffer_cache[HYPERCALL_BUFFER_CACHE_SIZE];
-
-    /*
-     * Hypercall buffer statistics. All protected by the global
-     * hypercall_buffer_cache lock.
-     */
-    int hypercall_buffer_total_allocations;
-    int hypercall_buffer_total_releases;
-    int hypercall_buffer_current_allocations;
-    int hypercall_buffer_maximum_allocations;
-    int hypercall_buffer_cache_hits;
-    int hypercall_buffer_cache_misses;
-    int hypercall_buffer_cache_toobig;
-
     /* Privcmd interface */
     int privcmdfd;
+
+    /* Hypercall interface */
+    xencall_handle *xcall;
 };
 
 int osdep_privcmd_open(xc_interface *xch);
@@ -233,24 +215,16 @@ void xc__hypercall_buffer_cache_release(xc_interface *xch);
  * Hypercall interfaces.
  */
 
-int do_xen_hypercall(xc_interface *xch, privcmd_hypercall_t *hypercall);
-
 static inline int do_xen_version(xc_interface *xch, int cmd, xc_hypercall_buffer_t *dest)
 {
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER_ARGUMENT(dest);
-
-    hypercall.op     = __HYPERVISOR_xen_version;
-    hypercall.arg[0] = (unsigned long) cmd;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(dest);
-
-    return do_xen_hypercall(xch, &hypercall);
+    return xencall2(xch->xcall, __HYPERVISOR_xen_version,
+                    cmd, HYPERCALL_BUFFER_AS_ARG(dest));
 }
 
 static inline int do_physdev_op(xc_interface *xch, int cmd, void *op, size_t len)
 {
     int ret = -1;
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BOUNCE(op, len, XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
 
     if ( xc_hypercall_bounce_pre(xch, op) )
@@ -259,11 +233,9 @@ static inline int do_physdev_op(xc_interface *xch, int cmd, void *op, size_t len
         goto out1;
     }
 
-    hypercall.op = __HYPERVISOR_physdev_op;
-    hypercall.arg[0] = (unsigned long) cmd;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(op);
-
-    if ( (ret = do_xen_hypercall(xch, &hypercall)) < 0 )
+    ret = xencall2(xch->xcall, __HYPERVISOR_physdev_op,
+                   cmd, HYPERCALL_BUFFER_AS_ARG(op));
+    if ( ret < 0 )
     {
         if ( errno == EACCES )
             DPRINTF("physdev operation failed -- need to"
@@ -278,7 +250,6 @@ out1:
 static inline int do_domctl(xc_interface *xch, struct xen_domctl *domctl)
 {
     int ret = -1;
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BOUNCE(domctl, sizeof(*domctl), XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
 
     domctl->interface_version = XEN_DOMCTL_INTERFACE_VERSION;
@@ -289,10 +260,9 @@ static inline int do_domctl(xc_interface *xch, struct xen_domctl *domctl)
         goto out1;
     }
 
-    hypercall.op     = __HYPERVISOR_domctl;
-    hypercall.arg[0] = HYPERCALL_BUFFER_AS_ARG(domctl);
-
-    if ( (ret = do_xen_hypercall(xch, &hypercall)) < 0 )
+    ret = xencall1(xch->xcall, __HYPERVISOR_domctl,
+                   HYPERCALL_BUFFER_AS_ARG(domctl));
+    if ( ret < 0 )
     {
         if ( errno == EACCES )
             DPRINTF("domctl operation failed -- need to"
@@ -307,7 +277,6 @@ static inline int do_domctl(xc_interface *xch, struct xen_domctl *domctl)
 static inline int do_sysctl(xc_interface *xch, struct xen_sysctl *sysctl)
 {
     int ret = -1;
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BOUNCE(sysctl, sizeof(*sysctl), XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
 
     sysctl->interface_version = XEN_SYSCTL_INTERFACE_VERSION;
@@ -318,9 +287,9 @@ static inline int do_sysctl(xc_interface *xch, struct xen_sysctl *sysctl)
         goto out1;
     }
 
-    hypercall.op     = __HYPERVISOR_sysctl;
-    hypercall.arg[0] = HYPERCALL_BUFFER_AS_ARG(sysctl);
-    if ( (ret = do_xen_hypercall(xch, &hypercall)) < 0 )
+    ret = xencall1(xch->xcall, __HYPERVISOR_sysctl,
+                   HYPERCALL_BUFFER_AS_ARG(sysctl));
+    if ( ret < 0 )
     {
         if ( errno == EACCES )
             DPRINTF("sysctl operation failed -- need to"
@@ -336,7 +305,6 @@ static inline int do_platform_op(xc_interface *xch,
                                  struct xen_platform_op *platform_op)
 {
     int ret = -1;
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BOUNCE(platform_op, sizeof(*platform_op),
                              XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
 
@@ -348,9 +316,9 @@ static inline int do_platform_op(xc_interface *xch,
         return -1;
     }
 
-    hypercall.op     = __HYPERVISOR_platform_op;
-    hypercall.arg[0] = HYPERCALL_BUFFER_AS_ARG(platform_op);
-    if ( (ret = do_xen_hypercall(xch, &hypercall)) < 0 )
+    ret = xencall1(xch->xcall, __HYPERVISOR_platform_op,
+                   HYPERCALL_BUFFER_AS_ARG(platform_op));
+    if ( ret < 0 )
     {
         if ( errno == EACCES )
             DPRINTF("platform operation failed -- need to"
@@ -366,13 +334,11 @@ static inline int do_multicall_op(xc_interface *xch,
                                   uint32_t nr_calls)
 {
     int ret = -1;
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER_ARGUMENT(call_list);
 
-    hypercall.op     = __HYPERVISOR_multicall;
-    hypercall.arg[0] = HYPERCALL_BUFFER_AS_ARG(call_list);
-    hypercall.arg[1] = nr_calls;
-    if ( (ret = do_xen_hypercall(xch, &hypercall)) < 0 )
+    ret = xencall2(xch->xcall, __HYPERVISOR_multicall,
+                   HYPERCALL_BUFFER_AS_ARG(call_list), nr_calls);
+    if ( ret < 0 )
     {
         if ( errno == EACCES )
             DPRINTF("multicall operation failed -- need to"
diff --git a/tools/libxc/xc_solaris.c b/tools/libxc/xc_solaris.c
index d719a11..cbac826 100644
--- a/tools/libxc/xc_solaris.c
+++ b/tools/libxc/xc_solaris.c
@@ -68,22 +68,6 @@ int osdep_privcmd_close(xc_interface *xch)
     return close(fd);
 }
 
-void *osdep_alloc_hypercall_buffer(xc_interface *xch, int npages)
-{
-    return xc_memalign(xch, XC_PAGE_SIZE, npages * XC_PAGE_SIZE);
-}
-
-static void osdep_free_hypercall_buffer(xc_interface *xch, void *ptr, int npages)
-{
-    free(ptr);
-}
-
-int do_xen_hypercall(xc_interface *xch, privcmd_hypercall_t *hypercall)
-{
-    int fd = xch->privcmdfd;
-    return ioctl(fd, IOCTL_PRIVCMD_HYPERCALL, hypercall);
-}
-
 void *xc_map_foreign_batch(xc_interface *xch,
                           uint32_t dom, int prot,
                           xen_pfn_t *arr, int num)
diff --git a/tools/libxc/xc_tmem.c b/tools/libxc/xc_tmem.c
index 02797bf..bd6bcd5 100644
--- a/tools/libxc/xc_tmem.c
+++ b/tools/libxc/xc_tmem.c
@@ -24,7 +24,6 @@
 static int do_tmem_op(xc_interface *xch, tmem_op_t *op)
 {
     int ret;
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BOUNCE(op, sizeof(*op), XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
 
     if ( xc_hypercall_bounce_pre(xch, op) )
@@ -33,9 +32,9 @@ static int do_tmem_op(xc_interface *xch, tmem_op_t *op)
         return -EFAULT;
     }
 
-    hypercall.op = __HYPERVISOR_tmem_op;
-    hypercall.arg[0] = HYPERCALL_BUFFER_AS_ARG(op);
-    if ((ret = do_xen_hypercall(xch, &hypercall)) < 0)
+    ret = xencall1(xch->xcall, __HYPERVISOR_tmem_op,
+                   HYPERCALL_BUFFER_AS_ARG(op));
+    if ( ret < 0 )
     {
         if ( errno == EACCES )
             DPRINTF("tmem operation failed -- need to"
diff --git a/tools/libxencall/Makefile b/tools/libxencall/Makefile
new file mode 100644
index 0000000..1b581db
--- /dev/null
+++ b/tools/libxencall/Makefile
@@ -0,0 +1,67 @@
+XEN_ROOT = $(CURDIR)/../..
+include $(XEN_ROOT)/tools/Rules.mk
+
+MAJOR    = 1
+MINOR    = 0
+SHLIB_LDFLAGS += -Wl,--version-script=libxencall.map
+
+CFLAGS   += -Werror -Wmissing-prototypes
+CFLAGS   += -I./include $(CFLAGS_xeninclude)
+CFLAGS   += $(CFLAGS_libxentoollog)
+
+SRCS-y                 += core.c buffer.c
+SRCS-$(CONFIG_Linux)   += linux.c
+SRCS-$(CONFIG_FreeBSD) += freebsd.c
+SRCS-$(CONFIG_SunOS)   += solaris.c
+SRCS-$(CONFIG_NetBSD)  += netbsd.c
+SRCS-$(CONFIG_MiniOS)  += minios.c
+
+LIB_OBJS := $(patsubst %.c,%.o,$(SRCS-y))
+PIC_OBJS := $(patsubst %.c,%.opic,$(SRCS-y))
+
+LIB := libxencall.a
+ifneq ($(nosharedlibs),y)
+LIB += libxencall.so
+endif
+
+.PHONY: all
+all: build
+
+.PHONY: build
+build:
+	$(MAKE) libs
+
+.PHONY: libs
+libs: headers.chk $(LIB)
+
+headers.chk: $(wildcard include/*.h)
+
+libxencall.a: $(LIB_OBJS)
+	$(AR) rc $@ $^
+
+libxencall.so: libxencall.so.$(MAJOR)
+	$(SYMLINK_SHLIB) $< $@
+libxencall.so.$(MAJOR): libxencall.so.$(MAJOR).$(MINOR)
+	$(SYMLINK_SHLIB) $< $@
+
+libxencall.so.$(MAJOR).$(MINOR): $(PIC_OBJS) libxencall.map
+	$(CC) $(LDFLAGS) $(PTHREAD_LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxencall.so.$(MAJOR) $(SHLIB_LDFLAGS) -o $@ $(PIC_OBJS) $(LDLIBS_libxentoollog) $(APPEND_LDFLAGS)
+
+.PHONY: install
+install: build
+	$(INSTALL_DIR) $(DESTDIR)$(libdir)
+	$(INSTALL_DIR) $(DESTDIR)$(includedir)
+	$(INSTALL_SHLIB) libxencall.so.$(MAJOR).$(MINOR) $(DESTDIR)$(libdir)
+	$(INSTALL_DATA) libxencall.a $(DESTDIR)$(libdir)
+	$(SYMLINK_SHLIB) libxencall.so.$(MAJOR).$(MINOR) $(DESTDIR)$(libdir)/libxencall.so.$(MAJOR)
+	$(SYMLINK_SHLIB) libxencall.so.$(MAJOR) $(DESTDIR)$(libdir)/libxencall.so
+	$(INSTALL_DATA) include/xencall.h $(DESTDIR)$(includedir)
+
+.PHONY: TAGS
+TAGS:
+	etags -t *.c *.h
+
+.PHONY: clean
+clean:
+	rm -rf *.rpm $(LIB) *~ $(DEPS) $(LIB_OBJS) $(PIC_OBJS)
+	rm -f headers.chk
diff --git a/tools/libxencall/buffer.c b/tools/libxencall/buffer.c
new file mode 100644
index 0000000..57e2f51
--- /dev/null
+++ b/tools/libxencall/buffer.c
@@ -0,0 +1,189 @@
+/*
+ * This library 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 of the License.
+ *
+ * This library 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 <errno.h>
+#include <string.h>
+#include <pthread.h>
+
+#include "private.h"
+
+#define DBGPRINTF(_m...) \
+	xtl_log(xcall->logger, XTL_DEBUG, -1, "xencall:buffer", _m)
+
+#define ROUNDUP(_x,_w) (((unsigned long)(_x)+(1UL<<(_w))-1) & ~((1UL<<(_w))-1))
+
+pthread_mutex_t cache_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static void cache_lock(xencall_handle *xcall)
+{
+    int saved_errno = errno;
+    if ( xcall->flags & XENCALL_OPENFLAG_NON_REENTRANT )
+        return;
+    pthread_mutex_lock(&cache_mutex);
+    /* Ignore pthread errors. */
+    errno = saved_errno;
+}
+
+static void cache_unlock(xencall_handle *xcall)
+{
+    int saved_errno = errno;
+    if ( xcall->flags & XENCALL_OPENFLAG_NON_REENTRANT )
+        return;
+    pthread_mutex_unlock(&cache_mutex);
+    /* Ignore pthread errors. */
+    errno = saved_errno;
+}
+
+static void *cache_alloc(xencall_handle *xcall, int nr_pages)
+{
+    void *p = NULL;
+
+    cache_lock(xcall);
+
+    xcall->buffer_total_allocations++;
+    xcall->buffer_current_allocations++;
+    if ( xcall->buffer_current_allocations > xcall->buffer_maximum_allocations )
+        xcall->buffer_maximum_allocations = xcall->buffer_current_allocations;
+
+    if ( nr_pages > 1 )
+    {
+        xcall->buffer_cache_toobig++;
+    }
+    else if ( xcall->buffer_cache_nr > 0 )
+    {
+        p = xcall->buffer_cache[--xcall->buffer_cache_nr];
+        xcall->buffer_cache_hits++;
+    }
+    else
+    {
+        xcall->buffer_cache_misses++;
+    }
+
+    cache_unlock(xcall);
+
+    return p;
+}
+
+static int cache_free(xencall_handle *xcall, void *p, int nr_pages)
+{
+    int rc = 0;
+
+    cache_lock(xcall);
+
+    xcall->buffer_total_releases++;
+    xcall->buffer_current_allocations--;
+
+    if ( nr_pages == 1 &&
+	 xcall->buffer_cache_nr < BUFFER_CACHE_SIZE )
+    {
+        xcall->buffer_cache[xcall->buffer_cache_nr++] = p;
+        rc = 1;
+    }
+
+    cache_unlock(xcall);
+
+    return rc;
+}
+
+void buffer_release_cache(xencall_handle *xcall)
+{
+    void *p;
+
+    cache_lock(xcall);
+
+    DBGPRINTF("total allocations:%d total releases:%d",
+              xcall->buffer_total_allocations,
+              xcall->buffer_total_releases);
+    DBGPRINTF("current allocations:%d maximum allocations:%d",
+              xcall->buffer_current_allocations,
+              xcall->buffer_maximum_allocations);
+    DBGPRINTF("cache current size:%d",
+              xcall->buffer_cache_nr);
+    DBGPRINTF("cache hits:%d misses:%d toobig:%d",
+              xcall->buffer_cache_hits,
+              xcall->buffer_cache_misses,
+              xcall->buffer_cache_toobig);
+
+    while ( xcall->buffer_cache_nr > 0 )
+    {
+        p = xcall->buffer_cache[--xcall->buffer_cache_nr];
+        osdep_free_pages(xcall, p, 1);
+    }
+
+    cache_unlock(xcall);
+}
+
+void *xencall_alloc_buffer_pages(xencall_handle *xcall, int nr_pages)
+{
+    void *p = cache_alloc(xcall, nr_pages);
+
+    if ( !p )
+        p = osdep_alloc_pages(xcall, nr_pages);
+
+    if (!p)
+        return NULL;
+
+    memset(p, 0, nr_pages * PAGE_SIZE);
+
+    return p;
+}
+
+void xencall_free_buffer_pages(xencall_handle *xcall, void *p, int nr_pages)
+{
+    if ( p == NULL )
+        return;
+
+    if ( !cache_free(xcall, p, nr_pages) )
+        osdep_free_pages(xcall, p, nr_pages);
+}
+
+struct allocation_header {
+    int nr_pages;
+};
+
+void *xencall_alloc_buffer(xencall_handle *xcall, size_t size)
+{
+    size_t actual_size = ROUNDUP(size + sizeof(struct allocation_header), PAGE_SHIFT);
+    int nr_pages = actual_size >> PAGE_SHIFT;
+    struct allocation_header *hdr;
+
+    hdr = xencall_alloc_buffer_pages(xcall, nr_pages);
+    if ( hdr == NULL )
+        return NULL;
+
+    hdr->nr_pages = nr_pages;
+
+    return (void *)(hdr+1);
+}
+
+void xencall_free_buffer(xencall_handle *xcall, void *p)
+{
+    struct allocation_header *hdr;
+
+    if (p == NULL)
+        return;
+
+    hdr = p;
+    --hdr;
+
+    xencall_free_buffer_pages(xcall, hdr, hdr->nr_pages);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxencall/core.c b/tools/libxencall/core.c
new file mode 100644
index 0000000..81250f0
--- /dev/null
+++ b/tools/libxencall/core.c
@@ -0,0 +1,141 @@
+/*
+ * This library 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 of the License.
+ *
+ * This library 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 <stdlib.h>
+
+#include "private.h"
+
+xencall_handle *xencall_open(xentoollog_logger *logger, unsigned open_flags)
+{
+	xencall_handle *xcall = malloc(sizeof(*xcall));
+    int rc;
+
+    if (!xcall) return NULL;
+
+    xcall->flags = open_flags;
+    xcall->buffer_cache_nr = 0;
+
+    xcall->buffer_total_allocations = 0;
+    xcall->buffer_total_releases = 0;
+    xcall->buffer_current_allocations = 0;
+    xcall->buffer_maximum_allocations = 0;
+    xcall->buffer_cache_hits = 0;
+    xcall->buffer_cache_misses = 0;
+    xcall->buffer_cache_toobig = 0;
+    xcall->logger = logger;
+    xcall->logger_tofree = NULL;
+
+    if (!xcall->logger) {
+        xcall->logger = xcall->logger_tofree =
+            (xentoollog_logger*)
+            xtl_createlogger_stdiostream(stderr, XTL_PROGRESS, 0);
+        if (!xcall->logger) goto err;
+    }
+
+    rc = osdep_xencall_open(xcall);
+    if ( rc  < 0 ) goto err;
+
+    return xcall;
+
+err:
+    osdep_xencall_close(xcall);
+    xtl_logger_destroy(xcall->logger_tofree);
+    free(xcall);
+    return NULL;
+}
+
+int xencall_close(xencall_handle *xcall)
+{
+    int rc;
+
+    rc = osdep_xencall_close(xcall);
+    buffer_release_cache(xcall);
+    xtl_logger_destroy(xcall->logger_tofree);
+    free(xcall);
+    return rc;
+}
+
+int xencall0(xencall_handle *xcall, unsigned int op)
+{
+    privcmd_hypercall_t call = {
+        .op = op,
+    };
+
+    return osdep_hypercall(xcall, &call);
+}
+
+int xencall1(xencall_handle *xcall, unsigned int op,
+             uint64_t arg1)
+{
+    privcmd_hypercall_t call = {
+        .op = op,
+        .arg = { arg1 },
+    };
+
+    return osdep_hypercall(xcall, &call);
+}
+
+int xencall2(xencall_handle *xcall, unsigned int op,
+             uint64_t arg1, uint64_t arg2)
+{
+    privcmd_hypercall_t call = {
+        .op = op,
+        .arg = { arg1, arg2 },
+    };
+
+    return osdep_hypercall(xcall, &call);
+}
+
+int xencall3(xencall_handle *xcall, unsigned int op,
+             uint64_t arg1, uint64_t arg2, uint64_t arg3)
+{
+    privcmd_hypercall_t call = {
+        .op = op,
+        .arg = { arg1, arg2, arg3},
+    };
+
+    return osdep_hypercall(xcall, &call);
+}
+
+int xencall4(xencall_handle *xcall, unsigned int op,
+             uint64_t arg1, uint64_t arg2, uint64_t arg3,
+             uint64_t arg4)
+{
+    privcmd_hypercall_t call = {
+        .op = op,
+        .arg = { arg1, arg2, arg3, arg4 },
+    };
+
+    return osdep_hypercall(xcall, &call);
+}
+
+int xencall5(xencall_handle *xcall, unsigned int op,
+             uint64_t arg1, uint64_t arg2, uint64_t arg3,
+             uint64_t arg4, uint64_t arg5)
+{
+    privcmd_hypercall_t call = {
+        .op = op,
+        .arg = { arg1, arg2, arg3, arg4, arg5 },
+    };
+
+    return osdep_hypercall(xcall, &call);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxencall/freebsd.c b/tools/libxencall/freebsd.c
new file mode 100644
index 0000000..3f162a0
--- /dev/null
+++ b/tools/libxencall/freebsd.c
@@ -0,0 +1,137 @@
+ /******************************************************************************
+ *
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * This library 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 of the License.
+ *
+ * This library 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.
+ *
+ * Split from xc_freebsd_osdep.c
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+
+#include "private.h"
+
+#define PRIVCMD_DEV     "/dev/xen/privcmd"
+
+int osdep_xencall_open(xencall_handle *xcall)
+{
+    int flags, saved_errno;
+    int fd = open(PRIVCMD_DEV, O_RDWR);
+
+    if ( fd == -1 )
+    {
+        PERROR("Could not obtain handle on privileged command interface "
+               PRIVCMD_DEV);
+        return -1;
+    }
+
+    /*
+     * Although we return the file handle as the 'xc handle' the API
+     * does not specify / guarentee that this integer is in fact
+     * a file handle. Thus we must take responsiblity to ensure
+     * it doesn't propagate (ie leak) outside the process.
+     */
+    if ( (flags = fcntl(fd, F_GETFD)) < 0 )
+    {
+        PERROR("Could not get file handle flags");
+        goto error;
+    }
+
+    flags |= FD_CLOEXEC;
+
+    if ( fcntl(fd, F_SETFD, flags) < 0 )
+    {
+        PERROR("Could not set file handle flags");
+        goto error;
+    }
+
+    xcall->fd = fd;
+    return 0;
+
+ error:
+    saved_errno = errno;
+    close(fd);
+    errno = saved_errno;
+
+    return -1;
+}
+
+int osdep_xencall_close(xencall_handle *xcall)
+{
+    int fd = xcall->fd;
+    if ( fd == -1 )
+        return 0;
+    return close(fd);
+}
+
+int osdep_hypercall(xencall_handle *xcall, privcmd_hypercall_t *hypercall)
+{
+    int fd = xcall->fd;
+    int ret;
+
+    ret = ioctl(fd, IOCTL_PRIVCMD_HYPERCALL, hypercall);
+
+    return (ret == 0) ? hypercall->retval : ret;
+}
+
+void *osdep_alloc_pages(xencall_handle *xcall, unsigned int npages)
+{
+    size_t size = npages * PAGE_SIZE;
+    void *p;
+
+    /* Address returned by mmap is page aligned. */
+    p = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS,
+             -1, 0);
+    if (p == NULL)
+        return NULL;
+
+    /*
+     * Since FreeBSD doesn't have the MAP_LOCKED flag,
+     * lock memory using mlock.
+     */
+    if ( mlock(p, size) < 0 )
+    {
+        munmap(p, size);
+        return NULL;
+    }
+
+    return p;
+}
+
+void osdep_free_pages(xencall_handle *xcall, void *ptr, unsigned int npages)
+{
+    int saved_errno = errno;
+    /* Unlock pages */
+    munlock(ptr, npages * PAGE_SIZE);
+
+    munmap(ptr, npages * PAGE_SIZE);
+    /* We MUST propagate the hypercall errno, not unmap call's. */
+    errno = saved_errno;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxencall/include/xencall.h b/tools/libxencall/include/xencall.h
new file mode 100644
index 0000000..87e4618
--- /dev/null
+++ b/tools/libxencall/include/xencall.h
@@ -0,0 +1,81 @@
+/*
+ * This library 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 of the License.
+ *
+ * This library 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.
+ */
+#ifndef XENCALL_H
+#define XENCALL_H
+
+/*
+ * This library allows you to make arbitrary hypercalls (subject to
+ * sufficient permission for the process and the domain itself). Note
+ * that while the library interface is stable the hypercalls are
+ * subject to their own rules.
+ */
+
+#include <stdint.h>
+#include <stddef.h>
+
+/* Callers who don't care don't need to #include <xentoollog.h> */
+typedef struct xentoollog_logger xentoollog_logger;
+
+typedef struct xencall_handle xencall_handle;
+
+/*
+ */
+#define XENCALL_OPENFLAG_NON_REENTRANT (1U<<0)
+
+/*
+ * Return a handle onto the hypercall driver.  Logs errors.
+ */
+xencall_handle *xencall_open(xentoollog_logger *logger, unsigned open_flags);
+
+/*
+ * Close a handle previously allocated with xencall_open().
+ */
+int xencall_close(xencall_handle *xcall);
+
+/*
+ * Call hypercalls with varying numbers of arguments.
+ */
+int xencall0(xencall_handle *xcall, unsigned int op);
+int xencall1(xencall_handle *xcall, unsigned int op,
+             uint64_t arg1);
+int xencall2(xencall_handle *xcall, unsigned int op,
+             uint64_t arg1, uint64_t arg2);
+int xencall3(xencall_handle *xcall, unsigned int op,
+             uint64_t arg1, uint64_t arg2, uint64_t arg3);
+int xencall4(xencall_handle *xcall, unsigned int op,
+             uint64_t arg1, uint64_t arg2, uint64_t arg3,
+             uint64_t arg4);
+int xencall5(xencall_handle *xcall, unsigned int op,
+             uint64_t arg1, uint64_t arg2, uint64_t arg3,
+             uint64_t arg4, uint64_t arg5);
+
+/*
+ * Allocate and free memory which is suitable for use as a pointer
+ * argument to a hypercall.
+ */
+void *xencall_alloc_buffer_pages(xencall_handle *xcall, int nr_pages);
+void xencall_free_buffer_pages(xencall_handle *xcall, void *p, int nr_pages);
+
+void *xencall_alloc_buffer(xencall_handle *xcall, size_t size);
+void xencall_free_buffer(xencall_handle *xcall, void *p);
+
+#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxencall/libxencall.map b/tools/libxencall/libxencall.map
new file mode 100644
index 0000000..2f96144
--- /dev/null
+++ b/tools/libxencall/libxencall.map
@@ -0,0 +1,19 @@
+VERS_1.0 {
+	global:
+		xencall_open;
+		xencall_close;
+
+		xencall0;
+		xencall1;
+		xencall2;
+		xencall3;
+		xencall4;
+		xencall5;
+		xencall6;
+
+		xencall_alloc_buffer;
+		xencall_free_buffer;
+		xencall_alloc_buffer_pages;
+		xencall_free_buffer_pages;
+	local: *; /* Do not expose anything by default */
+};
diff --git a/tools/libxencall/linux.c b/tools/libxencall/linux.c
new file mode 100644
index 0000000..9a93f75
--- /dev/null
+++ b/tools/libxencall/linux.c
@@ -0,0 +1,129 @@
+/*
+ * This library 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 of the License.
+ *
+ * This library 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.
+ *
+ * Split out from xc_linus_osdep.c:
+ *
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+
+#include "private.h"
+
+int osdep_xencall_open(xencall_handle *xcall)
+{
+    int flags, saved_errno;
+    int fd = open("/proc/xen/privcmd", O_RDWR);
+
+    if ( fd == -1 )
+    {
+        PERROR("Could not obtain handle on privileged command interface");
+        return -1;
+    }
+
+    /* Although we return the file handle as the 'xc handle' the API
+       does not specify / guarentee that this integer is in fact
+       a file handle. Thus we must take responsiblity to ensure
+       it doesn't propagate (ie leak) outside the process */
+    if ( (flags = fcntl(fd, F_GETFD)) < 0 )
+    {
+        PERROR("Could not get file handle flags");
+        goto error;
+    }
+
+    flags |= FD_CLOEXEC;
+
+    if ( fcntl(fd, F_SETFD, flags) < 0 )
+    {
+        PERROR("Could not set file handle flags");
+        goto error;
+    }
+
+    xcall->fd = fd;
+    return 0;
+
+ error:
+    saved_errno = errno;
+    close(fd);
+    errno = saved_errno;
+    return -1;
+}
+
+int osdep_xencall_close(xencall_handle *xcall)
+{
+    int fd = xcall->fd;
+    if (fd == -1)
+        return 0;
+    return close(fd);
+}
+
+int osdep_hypercall(xencall_handle *xcall, privcmd_hypercall_t *hypercall)
+{
+    return ioctl(xcall->fd, IOCTL_PRIVCMD_HYPERCALL, hypercall);
+}
+
+void *osdep_alloc_pages(xencall_handle *xcall, unsigned int npages)
+{
+    size_t size = npages * PAGE_SIZE;
+    void *p;
+    int rc, saved_errno;
+
+    /* Address returned by mmap is page aligned. */
+    p = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_LOCKED, -1, 0);
+    if ( p == MAP_FAILED )
+    {
+        PERROR("xc_alloc_hypercall_buffer: mmap failed");
+        return NULL;
+    }
+
+    /* Do not copy the VMA to child process on fork. Avoid the page being COW
+        on hypercall. */
+    rc = madvise(p, npages * PAGE_SIZE, MADV_DONTFORK);
+    if ( rc < 0 )
+    {
+        PERROR("xc_alloc_hypercall_buffer: madvise failed");
+        goto out;
+    }
+
+    return p;
+
+out:
+    saved_errno = errno;
+    (void)munmap(p, size);
+    errno = saved_errno;
+    return NULL;
+}
+
+void osdep_free_pages(xencall_handle *xcall, void *ptr, unsigned int npages)
+{
+    int saved_errno = errno;
+    /* Recover the VMA flags. Maybe it's not necessary */
+    madvise(ptr, npages * PAGE_SIZE, MADV_DOFORK);
+
+    munmap(ptr, npages * PAGE_SIZE);
+    /* We MUST propagate the hypercall errno, not unmap call's. */
+    errno = saved_errno;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxencall/minios.c b/tools/libxencall/minios.c
new file mode 100644
index 0000000..de8036b
--- /dev/null
+++ b/tools/libxencall/minios.c
@@ -0,0 +1,78 @@
+/*
+ * This library 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 of the License.
+ *
+ * This library 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.
+ *
+ * Split out from xc_minios.c
+ *
+ * Copyright 2007-2008 Samuel Thibault <samuel.thibault@eu.citrix.com>.
+ */
+
+#include <mini-os/types.h>
+#include <mini-os/os.h>
+#include <mini-os/mm.h>
+#include <mini-os/lib.h>
+
+#include <errno.h>
+#include <malloc.h>
+
+#include "private.h"
+
+int osdep_xencall_open(xencall_handle *xcall)
+{
+    /* No fd required */
+    return 0;
+}
+
+int osdep_xencall_close(xencall_handle *xcall)
+{
+    return 0;
+}
+
+int osdep_hypercall(xencall_handle *xcall, privcmd_hypercall_t *hypercall)
+{
+    multicall_entry_t call;
+    int i, ret;
+
+    call.op = hypercall->op;
+    for (i = 0; i < 5; i++)
+        call.args[i] = hypercall->arg[i];
+
+    ret = HYPERVISOR_multicall(&call, 1);
+
+    if (ret < 0) {
+	errno = -ret;
+	return -1;
+    }
+    if ((long) call.result < 0) {
+        errno = - (long) call.result;
+        return -1;
+    }
+    return call.result;
+}
+
+void *osdep_alloc_pages(xencall_handle *xcall, unsigned npages)
+{
+    return memalign(PAGE_SIZE, npages * PAGE_SIZE);
+}
+
+void osdep_free_pages(xencall_handle *xcall, void *ptr, unsigned npages)
+{
+    free(ptr);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxencall/netbsd.c b/tools/libxencall/netbsd.c
new file mode 100644
index 0000000..b1d476a
--- /dev/null
+++ b/tools/libxencall/netbsd.c
@@ -0,0 +1,118 @@
+/******************************************************************************
+ *
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * This library 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 of the License.
+ *
+ * This library 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.
+ *
+ * Split from xc_netbsd.c
+ */
+
+#include "xc_private.h"
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <malloc.h>
+#include <sys/mman.h>
+
+int osdep_xencall_open(xencall_handle *xcall)
+{
+    int flags, saved_errno;
+    int fd = open("/kern/xen/privcmd", O_RDWR);
+
+    if ( fd == -1 )
+    {
+        PERROR("Could not obtain handle on privileged command interface");
+        return -1;
+    }
+
+    /* Although we return the file handle as the 'xc handle' the API
+       does not specify / guarentee that this integer is in fact
+       a file handle. Thus we must take responsiblity to ensure
+       it doesn't propagate (ie leak) outside the process */
+    if ( (flags = fcntl(fd, F_GETFD)) < 0 )
+    {
+        PERROR("Could not get file handle flags");
+        goto error;
+    }
+    flags |= FD_CLOEXEC;
+    if ( fcntl(fd, F_SETFD, flags) < 0 )
+    {
+        PERROR("Could not set file handle flags");
+        goto error;
+    }
+
+    xcall->fd = fd;
+    return 0;
+
+ error:
+    saved_errno = errno;
+    close(fd);
+    errno = saved_errno;
+    return -1;
+}
+
+int osdep_xencall_close(xencall_handle *xcall)
+{
+    int fd = xcall->fd;
+    return close(fd);
+}
+
+void *osdep_alloc_hypercall_buffer(xencall_handle *xcall, unsigned int npages)
+{
+    size_t size = npages * XC_PAGE_SIZE;
+    void *p;
+
+    p = xc_memalign(xcall, XC_PAGE_SIZE, size);
+    if (!p)
+        return NULL;
+
+    if ( mlock(p, size) < 0 )
+    {
+        free(p);
+        return NULL;
+    }
+    return p;
+}
+
+void osdep_free_hypercall_buffer(xencall_handle *xcall, void *ptr,
+                                 unsigned int npages)
+{
+    (void) munlock(ptr, npages * XC_PAGE_SIZE);
+    free(ptr);
+}
+
+int do_xen_hypercall(xencall_handle *xcall, privcmd_hypercall_t *hypercall)
+{
+    int fd = xcall->fd;
+    int error = ioctl(fd, IOCTL_PRIVCMD_HYPERCALL, hypercall);
+
+    /*
+     * Since NetBSD ioctl can only return 0 on success or < 0 on
+     * error, if we want to return a value from ioctl we should
+     * do so by setting hypercall->retval, to mimic Linux ioctl
+     * implementation.
+     */
+    if (error < 0)
+        return error;
+    else
+        return hypercall->retval;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxencall/private.h b/tools/libxencall/private.h
new file mode 100644
index 0000000..af727fd
--- /dev/null
+++ b/tools/libxencall/private.h
@@ -0,0 +1,68 @@
+#ifndef XENCALL_PRIVATE_H
+#define XENCALL_PRIVATE_H
+
+#include <xentoollog.h>
+
+#include <xencall.h>
+
+#include <xen/xen.h>
+#include <xen/sys/privcmd.h>
+
+#ifndef PAGE_SHIFT /* Mini-os, Yukk */
+#define PAGE_SHIFT           12
+#endif
+#ifndef __MINIOS__ /* Yukk */
+#define PAGE_SIZE            (1UL << PAGE_SHIFT)
+#define PAGE_MASK            (~(PAGE_SIZE-1))
+#endif
+
+struct xencall_handle {
+    xentoollog_logger *logger, *logger_tofree;
+    unsigned flags;
+    int fd;
+
+    /*
+     * A simple cache of unused, single page, hypercall buffers
+     *
+     * Protected by a global lock.
+     */
+#define BUFFER_CACHE_SIZE 4
+    int buffer_cache_nr;
+    void *buffer_cache[BUFFER_CACHE_SIZE];
+
+    /*
+     * Hypercall buffer statistics. All protected by the global
+     * buffer_cache lock.
+     */
+    int buffer_total_allocations;
+    int buffer_total_releases;
+    int buffer_current_allocations;
+    int buffer_maximum_allocations;
+    int buffer_cache_hits;
+    int buffer_cache_misses;
+    int buffer_cache_toobig;
+};
+
+int osdep_xencall_open(xencall_handle *xcall);
+int osdep_xencall_close(xencall_handle *xcall);
+
+int osdep_hypercall(xencall_handle *xcall, privcmd_hypercall_t *hypercall);
+
+void *osdep_alloc_pages(xencall_handle *xcall, unsigned int nr_pages);
+void osdep_free_pages(xencall_handle *xcall, void *p, unsigned int nr_pages);
+
+void buffer_release_cache(xencall_handle *xcall);
+
+#define PERROR(_f...) xtl_log(xcall->logger, XTL_ERROR, errno, "xencall", _f)
+
+#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxencall/solaris.c b/tools/libxencall/solaris.c
new file mode 100644
index 0000000..9887bf6
--- /dev/null
+++ b/tools/libxencall/solaris.c
@@ -0,0 +1,94 @@
+/******************************************************************************
+ *
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * This library 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 of the License.
+ *
+ * This library 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.
+ *
+ * Split from xc_solaris.c
+ */
+
+#include "xc_private.h"
+
+#include <xen/memory.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <malloc.h>
+
+int osdep_xencall_open(xencall_handle *xcall)
+{
+    int flags, saved_errno;
+    int fd = open("/dev/xen/privcmd", O_RDWR);
+
+    if ( fd == -1 )
+    {
+        PERROR("Could not obtain handle on privileged command interface");
+        return -1;
+    }
+
+    /* Although we return the file handle as the 'xc handle' the API
+       does not specify / guarentee that this integer is in fact
+       a file handle. Thus we must take responsiblity to ensure
+       it doesn't propagate (ie leak) outside the process */
+    if ( (flags = fcntl(fd, F_GETFD)) < 0 )
+    {
+        PERROR("Could not get file handle flags");
+        goto error;
+    }
+    flags |= FD_CLOEXEC;
+    if ( fcntl(fd, F_SETFD, flags) < 0 )
+    {
+        PERROR("Could not set file handle flags");
+        goto error;
+    }
+
+    xcall->fd = fd;
+    return 0;
+
+ error:
+    saved_errno = errno;
+    close(fd);
+    errno = saved_errno;
+    return -1;
+}
+
+int osdep_xencall_close(xencall_handle *xcall)
+{
+    int fd = xcall->fd;
+    return close(fd);
+}
+
+void *osdep_alloc_hypercall_buffer(xencall_handle *xcall, unsigned int npages)
+{
+    return xc_memalign(xcall, XC_PAGE_SIZE, npages * XC_PAGE_SIZE);
+}
+
+void osdep_free_hypercall_buffer(xencall_handle *xcall, void *ptr,
+                                 unsigned int npages)
+{
+    free(ptr);
+}
+
+int do_xen_hypercall(xencall_handle *xcall, privcmd_hypercall_t *hypercall)
+{
+    int fd = xcall->fd;
+    return ioctl(fd, IOCTL_PRIVCMD_HYPERCALL, hypercall);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/misc/Makefile b/tools/misc/Makefile
index cf6a475..a2ef0ec 100644
--- a/tools/misc/Makefile
+++ b/tools/misc/Makefile
@@ -87,12 +87,12 @@ xenlockprof: xenlockprof.o
 	$(CC) $(LDFLAGS) -o $@ $< $(LDLIBS_libxenctrl) $(APPEND_LDFLAGS)
 
 # xen-hptool incorrectly uses libxc internals
-xen-hptool.o: CFLAGS += -I$(XEN_ROOT)/tools/libxc
+xen-hptool.o: CFLAGS += -I$(XEN_ROOT)/tools/libxc $(CFLAGS_libxencall)
 xen-hptool: xen-hptool.o
 	$(CC) $(LDFLAGS) -o $@ $< $(LDLIBS_libxenevtchn) $(LDLIBS_libxenctrl) $(LDLIBS_libxenguest) $(LDLIBS_libxenstore) $(APPEND_LDFLAGS)
 
 # xen-mfndump incorrectly uses libxc internals
-xen-mfndump.o: CFLAGS += -I$(XEN_ROOT)/tools/libxc
+xen-mfndump.o: CFLAGS += -I$(XEN_ROOT)/tools/libxc $(CFLAGS_libxencall)
 xen-mfndump: xen-mfndump.o
 	$(CC) $(LDFLAGS) -o $@ $< $(LDLIBS_libxenevtchn) $(LDLIBS_libxenctrl) $(LDLIBS_libxenguest) $(APPEND_LDFLAGS)
 
diff --git a/tools/xcutils/Makefile b/tools/xcutils/Makefile
index 2d1f112..e127af8 100644
--- a/tools/xcutils/Makefile
+++ b/tools/xcutils/Makefile
@@ -16,7 +16,7 @@ PROGRAMS = readnotes lsevtchn
 CFLAGS += -Werror
 
 # incorrectly uses libxc internals
-CFLAGS_readnotes.o  := $(CFLAGS_libxenevtchn) $(CFLAGS_libxenctrl) $(CFLAGS_libxenguest) -I$(XEN_ROOT)/tools/libxc
+CFLAGS_readnotes.o  := $(CFLAGS_libxenevtchn) $(CFLAGS_libxenctrl) $(CFLAGS_libxenguest) -I$(XEN_ROOT)/tools/libxc $(CFLAGS_libxencall)
 CFLAGS_lsevtchn.o   := $(CFLAGS_libxenevtchn) $(CFLAGS_libxenctrl)
 
 .PHONY: all
diff --git a/tools/xenpaging/Makefile b/tools/xenpaging/Makefile
index d491867..64876b3 100644
--- a/tools/xenpaging/Makefile
+++ b/tools/xenpaging/Makefile
@@ -2,7 +2,7 @@ XEN_ROOT=$(CURDIR)/../..
 include $(XEN_ROOT)/tools/Rules.mk
 
 # xenpaging.c and file_ops.c incorrectly use libxc internals
-CFLAGS += $(CFLAGS_libxentoollog) $(CFLAGS_libxenevtchn) $(CFLAGS_libxenctrl) $(CFLAGS_libxenstore) $(PTHREAD_CFLAGS) -I$(XEN_ROOT)/tools/libxc
+CFLAGS += $(CFLAGS_libxentoollog) $(CFLAGS_libxenevtchn) $(CFLAGS_libxenctrl) $(CFLAGS_libxenstore) $(PTHREAD_CFLAGS) -I$(XEN_ROOT)/tools/libxc $(CFLAGS_libxencall)
 LDLIBS += $(LDLIBS_libxentoollog) $(LDLIBS_libxenevtchn) $(LDLIBS_libxenctrl) $(LDLIBS_libxenstore) $(PTHREAD_LIBS)
 LDFLAGS += $(PTHREAD_LDFLAGS)
 
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH XEN v2 11/15] tools/libxc: drop xc_map_foreign_bulk_compat wrappers
  2015-07-15 15:46 [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries Ian Campbell
                   ` (9 preceding siblings ...)
  2015-07-15 15:46 ` [PATCH XEN v2 10/15] tools: Refactor hypercall calling wrappers into libxencall Ian Campbell
@ 2015-07-15 15:46 ` Ian Campbell
  2015-07-15 15:47 ` [PATCH XEN v2 12/15] tools: Remove xc_map_foreign_batch Ian Campbell
                   ` (16 subsequent siblings)
  27 siblings, 0 replies; 55+ messages in thread
From: Ian Campbell @ 2015-07-15 15:46 UTC (permalink / raw)
  To: ian.jackson, wei.liu2, xen-devel
  Cc: roger.pau, Ian Campbell, stefano.stabellini

On Solaris and NetBSD xc_map_foreign_bulk is implemented by calling
xc_map_foreign_bulk_compat and xc_map_foreign_bulk_compat is exposed
as a symbol by libxenctrl.so.

Remove these wrappers and turn the compat function into the real thing
surrounded by the appropriate ifdef.

As this is a compat function all new ports should instead implement
xc_map_foreign_bulk properly, hence the ifdef should never be
expanded.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
---
 docs/misc/toolstack-library-abis.pandoc |  4 ----
 tools/libxc/xc_foreign_memory.c         | 13 +++++++++----
 tools/libxc/xc_netbsd.c                 |  7 -------
 tools/libxc/xc_private.h                |  5 -----
 tools/libxc/xc_solaris.c                |  7 -------
 5 files changed, 9 insertions(+), 27 deletions(-)

diff --git a/docs/misc/toolstack-library-abis.pandoc b/docs/misc/toolstack-library-abis.pandoc
index 8339834..271e4b5 100644
--- a/docs/misc/toolstack-library-abis.pandoc
+++ b/docs/misc/toolstack-library-abis.pandoc
@@ -276,10 +276,6 @@ Interface                         Underlying interface           Known external
 `xc_map_foreign_ranges`
 `xc_map_foreign_batch`
 `xc_map_foreign_bulk`             `IOCTL_PRIVCMD_MMAPBATCH_V2`   qemu-dm
-`xc_map_foreign_bulk_compat`                                     private
-
-`xc_map_foreign_bulk_compat` is a stub for all not yet converted OSes
-and is used by netbsd & solaris.
 
 ### Managing guest memory map
 
diff --git a/tools/libxc/xc_foreign_memory.c b/tools/libxc/xc_foreign_memory.c
index 53b6c9a..da77e9d 100644
--- a/tools/libxc/xc_foreign_memory.c
+++ b/tools/libxc/xc_foreign_memory.c
@@ -51,10 +51,14 @@ void *xc_map_foreign_pages(xc_interface *xch, uint32_t dom, int prot,
     return res;
 }
 
-/* stub for all not yet converted OSes */
-void *xc_map_foreign_bulk_compat(xc_interface *xch,
-                                 uint32_t dom, int prot,
-                                 const xen_pfn_t *arr, int *err, unsigned int num)
+/*
+ * stub for all not yet converted OSes (NetBSD and Solaris). New OSes should
+ * just implement xc_map_foreign_bulk.
+ */
+#if defined(__NetBSD__) || defined(__sun__)
+void *xc_map_foreign_bulk(xc_interface *xch,
+                          uint32_t dom, int prot,
+                          const xen_pfn_t *arr, int *err, unsigned int num)
 {
     xen_pfn_t *pfn;
     unsigned int i;
@@ -91,6 +95,7 @@ void *xc_map_foreign_bulk_compat(xc_interface *xch,
 
     return ret;
 }
+#endif
 
 /*
  * Local variables:
diff --git a/tools/libxc/xc_netbsd.c b/tools/libxc/xc_netbsd.c
index 78683a2..a61e52f 100644
--- a/tools/libxc/xc_netbsd.c
+++ b/tools/libxc/xc_netbsd.c
@@ -68,13 +68,6 @@ int osdep_privcmd_close(xc_interface *xch)
     return close(fd);
 }
 
-void *xc_map_foreign_bulk(xc_interface *xch,
-                          uint32_t dom, int prot,
-                          const xen_pfn_t *arr, int *err, unsigned int num)
-{
-    return xc_map_foreign_bulk_compat(xch, dom, prot, arr, err, num);
-}
-
 void *xc_map_foreign_batch(xc_interface *xch,
                            uint32_t dom, int prot,
                            xen_pfn_t *arr, int num)
diff --git a/tools/libxc/xc_private.h b/tools/libxc/xc_private.h
index 2288660..c8c2bdc 100644
--- a/tools/libxc/xc_private.h
+++ b/tools/libxc/xc_private.h
@@ -108,11 +108,6 @@ int osdep_privcmd_close(xc_interface *xch);
 void *osdep_alloc_hypercall_buffer(xc_interface *xch, int npages);
 void osdep_free_hypercall_buffer(xc_interface *xch, void *ptr, int npages);
 
-/* Stub for not yet converted OSes */
-void *xc_map_foreign_bulk_compat(xc_interface *xch,
-                                 uint32_t dom, int prot,
-                                 const xen_pfn_t *arr, int *err, unsigned int num);
-
 void xc_report_error(xc_interface *xch, int code, const char *fmt, ...)
     __attribute__((format(printf,3,4)));
 void xc_reportv(xc_interface *xch, xentoollog_logger *lg, xentoollog_level,
diff --git a/tools/libxc/xc_solaris.c b/tools/libxc/xc_solaris.c
index cbac826..1e1a0c4 100644
--- a/tools/libxc/xc_solaris.c
+++ b/tools/libxc/xc_solaris.c
@@ -95,13 +95,6 @@ void *xc_map_foreign_batch(xc_interface *xch,
 
 }
 
-void *xc_map_foreign_bulk(xc_interface *xch,
-                          uint32_t dom, int prot,
-                          const xen_pfn_t *arr, int *err, unsigned int num)
-{
-    return xc_map_foreign_bulk_compat(xch, dom, prot, arr, err, num);
-}
-
 void *xc_map_foreign_range(xc_interface *xch,
                            uint32_t dom,
                            int size, int prot,
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH XEN v2 12/15] tools: Remove xc_map_foreign_batch
  2015-07-15 15:46 [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries Ian Campbell
                   ` (10 preceding siblings ...)
  2015-07-15 15:46 ` [PATCH XEN v2 11/15] tools/libxc: drop xc_map_foreign_bulk_compat wrappers Ian Campbell
@ 2015-07-15 15:47 ` Ian Campbell
  2015-07-15 16:08   ` George Dunlap
  2015-07-15 15:47 ` [PATCH XEN v2 13/15] tools: Implement xc_map_foreign_range(s) in terms of common helper Ian Campbell
                   ` (15 subsequent siblings)
  27 siblings, 1 reply; 55+ messages in thread
From: Ian Campbell @ 2015-07-15 15:47 UTC (permalink / raw)
  To: ian.jackson, wei.liu2, xen-devel
  Cc: George Dunlap, roger.pau, Ian Campbell, stefano.stabellini

It can trivially be replaced by xc_map_foreign_bulk which is the
interface I want to move to going forward. All in tree users are
trivially converted by supplying the appropriate error array and
adjusting the what error handling exists (which in many cases is not
much).

This reduces the twist maze of xc_map_foreign_* by one, which will be
useful when trying to come up with an underlying stable interface.

NetBSD and Solaris implemented xc_map_foreign_bulk in terms of
xc_map_foreign_batch via a compat layer, so xc_map_foreign_batch
becomes an internal osdep for them. New OS ports should always
implement xc_map_foreign_bulk instead.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
Cc: George Dunlap <george.dunlap@eu.citrix.com>
---
 docs/misc/toolstack-library-abis.pandoc | 17 +++-------
 tools/libxc/include/xenctrl.h           | 10 ------
 tools/libxc/xc_foreign_memory.c         |  4 ++-
 tools/libxc/xc_linux_osdep.c            | 59 ++-------------------------------
 tools/libxc/xc_minios.c                 | 22 ------------
 tools/libxc/xc_netbsd.c                 | 10 +++---
 tools/libxc/xc_solaris.c                |  6 ++--
 tools/libxc/xc_vm_event.c               | 25 ++++++++++----
 tools/xenmon/xenbaked.c                 | 19 ++++++++---
 tools/xenpaging/pagein.c                |  4 ++-
 tools/xenpaging/xenpaging.c             | 12 ++++---
 tools/xentrace/xentrace.c               | 10 +++---
 12 files changed, 68 insertions(+), 130 deletions(-)

diff --git a/docs/misc/toolstack-library-abis.pandoc b/docs/misc/toolstack-library-abis.pandoc
index 271e4b5..4ad6c7d 100644
--- a/docs/misc/toolstack-library-abis.pandoc
+++ b/docs/misc/toolstack-library-abis.pandoc
@@ -274,7 +274,6 @@ Interface                         Underlying interface           Known external
 `xc_map_foreign_pages`            `IOCTL_PRIVCMD_MMAP...`        qemu-pv
 `xc_map_foreign_range`            `IOCTL_PRIVCMD_MMAP...`        qemu-dm, and qemu-pv
 `xc_map_foreign_ranges`
-`xc_map_foreign_batch`
 `xc_map_foreign_bulk`             `IOCTL_PRIVCMD_MMAPBATCH_V2`   qemu-dm
 
 ### Managing guest memory map
@@ -883,7 +882,6 @@ osdep level interfaces:
 
 Interface            Linux Minios Netbsd Freebsd Solaris
 -------------------- ----- ------ ------ ------- -------
-`map_foreign_batch`  Y     Y      Y              Y
 `map_foreign_bulk`   Y     Y      compat Y       compat
 `map_foreign_range`  Y     Y      Y      Y       Y
 `map_foreign_ranges` Y     Y      Y      Y       Y
@@ -897,7 +895,6 @@ Some osdep call other `xc_map_foreign_*` recursivley:
 
 Interface            Linux                        FreeBSD
 -------------------- ---------------------------- -------------------------
-`map_foreign_batch`  `IOCTL_PRIVCMD_MMAPBATCH`    N/A
 `map_foreign_bulk`   `IOCTL_PRIVCMD_MMAPBATCH_V2` `IOCTL_PRIVCMD_MMAPBATCH`
 `map_foreign_range`  `xc_map_foreign_pages`       `xc_map_foreign_pages`
 `map_foreign_ranges` `xc_map_foreign_pages`       `xc_map_foreign_pages`
@@ -909,17 +906,14 @@ Interface               Underlying interface
 `xc_map_foreign_pages`  `xc_map_foreign_bulk`
 `xc_map_foreign_range`  `osdep: map_foreign_range`
 `xc_map_foreign_ranges` `osdep: map_foreign_ranges`
-`xc_map_foreign_batch`  `osdep: map_foreign_batch`
 `xc_map_foreign_bulk`   `osdep: map_foreign_bulk`
 
 `osdep: *` have been collapsed since osdep layer was removed.
 
-`xc_map_foreign_bulk_compat` is an internal helper used by osdep
-backends which have not implemented there own version. It uses
-`xc_map_foreign_batch`.
-
-`xc_map_foreign_batch_single` is part of linux osdep, but name has
-leaked.
+`xc_map_foreign_bulk` can be an internal compat helper used by oses
+which have not implemented their own version. It used to use
+`xc_map_foreign_batch` which is now an osdep for those OSes which need
+it.
 
 Interface               Internal users               External users
 ----------------------  --------------               --------------
@@ -928,11 +922,10 @@ Interface               Internal users               External users
                         mfndump, memshrtool, xenmon,
                         xenstored, xentrace
 `xc_map_foreign_ranges` NONE
-`xc_map_foreign_batch`  xenmon, xenpaging, xentrace
 `xc_map_foreign_bulk`   used recursively             qemu-dm
 
 Only one interface should become a stable API. Something based on
 `xc_map_foreign_bulk` seems most appropriate (it is used by
 `xc_map_foreign_pages` as well as by xc_map_foreign_range` and
 `xc_map_foreign_ranges` on Linux + FreeBSD. A compat version exists in
-terms for `xc_map_foreign_batch` for other OSes.
+terms of `xc_map_foreign_batch` for other OSes.
diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h
index 61f68bb..201fd70 100644
--- a/tools/libxc/include/xenctrl.h
+++ b/tools/libxc/include/xenctrl.h
@@ -1367,16 +1367,6 @@ void *xc_map_foreign_pages(xc_interface *xch, uint32_t dom, int prot,
                            const xen_pfn_t *arr, int num );
 
 /**
- * DEPRECATED - use xc_map_foreign_bulk() instead.
- *
- * Like xc_map_foreign_pages(), except it can succeeed partially.
- * When a page cannot be mapped, its PFN in @arr is or'ed with
- * 0xF0000000 to indicate the error.
- */
-void *xc_map_foreign_batch(xc_interface *xch, uint32_t dom, int prot,
-                           xen_pfn_t *arr, int num );
-
-/**
  * Like xc_map_foreign_pages(), except it can succeed partially.
  * When a page cannot be mapped, its respective field in @err is
  * set to the corresponding errno value.
diff --git a/tools/libxc/xc_foreign_memory.c b/tools/libxc/xc_foreign_memory.c
index da77e9d..ae133a1 100644
--- a/tools/libxc/xc_foreign_memory.c
+++ b/tools/libxc/xc_foreign_memory.c
@@ -56,6 +56,8 @@ void *xc_map_foreign_pages(xc_interface *xch, uint32_t dom, int prot,
  * just implement xc_map_foreign_bulk.
  */
 #if defined(__NetBSD__) || defined(__sun__)
+void *osdep_map_foreign_batch(xc_interface *xch, uint32_t dom, int prot,
+                              xen_pfn_t *arr, int num );
 void *xc_map_foreign_bulk(xc_interface *xch,
                           uint32_t dom, int prot,
                           const xen_pfn_t *arr, int *err, unsigned int num)
@@ -76,7 +78,7 @@ void *xc_map_foreign_bulk(xc_interface *xch,
     }
 
     memcpy(pfn, arr, num * sizeof(*arr));
-    ret = xc_map_foreign_batch(xch, dom, prot, pfn, num);
+    ret = osdep_map_foreign_batch(xch, dom, prot, pfn, num);
 
     if (ret) {
         for (i = 0; i < num; ++i)
diff --git a/tools/libxc/xc_linux_osdep.c b/tools/libxc/xc_linux_osdep.c
index 488e8df..6641bd1 100644
--- a/tools/libxc/xc_linux_osdep.c
+++ b/tools/libxc/xc_linux_osdep.c
@@ -86,8 +86,8 @@ int osdep_privcmd_close(xc_interface *xch)
     return close(fd);
 }
 
-static int xc_map_foreign_batch_single(int fd, uint32_t dom,
-                                       xen_pfn_t *mfn, unsigned long addr)
+static int map_foreign_batch_single(int fd, uint32_t dom,
+                                    xen_pfn_t *mfn, unsigned long addr)
 {
     privcmd_mmapbatch_t ioctlx;
     int rc;
@@ -108,59 +108,6 @@ static int xc_map_foreign_batch_single(int fd, uint32_t dom,
     return rc;
 }
 
-void *xc_map_foreign_batch(xc_interface *xch,
-                           uint32_t dom, int prot,
-                           xen_pfn_t *arr, int num)
-{
-    int fd = xch->privcmdfd;
-    privcmd_mmapbatch_t ioctlx;
-    void *addr;
-    int rc;
-
-    addr = mmap(NULL, num << XC_PAGE_SHIFT, prot, MAP_SHARED, fd, 0);
-    if ( addr == MAP_FAILED )
-    {
-        PERROR("xc_map_foreign_batch: mmap failed");
-        return NULL;
-    }
-
-    ioctlx.num = num;
-    ioctlx.dom = dom;
-    ioctlx.addr = (unsigned long)addr;
-    ioctlx.arr = arr;
-
-    rc = ioctl(fd, IOCTL_PRIVCMD_MMAPBATCH, &ioctlx);
-    if ( (rc < 0) && (errno == ENOENT) )
-    {
-        int i;
-
-        for ( i = 0; i < num; i++ )
-        {
-            if ( (arr[i] & PRIVCMD_MMAPBATCH_MFN_ERROR) ==
-                           PRIVCMD_MMAPBATCH_PAGED_ERROR )
-            {
-                unsigned long paged_addr = (unsigned long)addr + (i << XC_PAGE_SHIFT);
-                rc = xc_map_foreign_batch_single(fd, dom, &arr[i],
-                                                 paged_addr);
-                if ( rc < 0 )
-                    goto out;
-            }
-        }
-    }
-
- out:
-    if ( rc < 0 )
-    {
-        int saved_errno = errno;
-        PERROR("xc_map_foreign_batch: ioctl failed");
-        (void)munmap(addr, num << XC_PAGE_SHIFT);
-        errno = saved_errno;
-        return NULL;
-    }
-
-    return addr;
-}
-
 /*
  * Retry mmap of all paged gfns in batches
  * retuns < 0 on fatal error
@@ -300,7 +247,7 @@ void *xc_map_foreign_bulk(xc_interface *xch,
                     err[i] = rc ?: -EINVAL;
                     continue;
                 }
-                rc = xc_map_foreign_batch_single(fd, dom, pfn + i,
+                rc = map_foreign_batch_single(fd, dom, pfn + i,
                         (unsigned long)addr + ((unsigned long)i<<XC_PAGE_SHIFT));
                 if ( rc < 0 )
                 {
diff --git a/tools/libxc/xc_minios.c b/tools/libxc/xc_minios.c
index 27a4c4a..ed20652 100644
--- a/tools/libxc/xc_minios.c
+++ b/tools/libxc/xc_minios.c
@@ -74,28 +74,6 @@ void *xc_map_foreign_bulk(xc_interface *xch,
     return map_frames_ex(arr, num, 1, 0, 1, dom, err, pt_prot);
 }
 
-void *xc_map_foreign_batch(xc_interface *xch,
-                           uint32_t dom, int prot,
-                           xen_pfn_t *arr, int num)
-{
-    unsigned long pt_prot = 0;
-    int err[num];
-    int i;
-    unsigned long addr;
-
-    if (prot & PROT_READ)
-	pt_prot = L1_PROT_RO;
-    if (prot & PROT_WRITE)
-	pt_prot = L1_PROT;
-
-    addr = (unsigned long) map_frames_ex(arr, num, 1, 0, 1, dom, err, pt_prot);
-    for (i = 0; i < num; i++) {
-        if (err[i])
-            arr[i] |= 0xF0000000;
-    }
-    return (void *) addr;
-}
-
 void *xc_map_foreign_range(xc_interface *xch,
                            uint32_t dom,
                            int size, int prot,
diff --git a/tools/libxc/xc_netbsd.c b/tools/libxc/xc_netbsd.c
index a61e52f..f02015c 100644
--- a/tools/libxc/xc_netbsd.c
+++ b/tools/libxc/xc_netbsd.c
@@ -68,16 +68,16 @@ int osdep_privcmd_close(xc_interface *xch)
     return close(fd);
 }
 
-void *xc_map_foreign_batch(xc_interface *xch,
-                           uint32_t dom, int prot,
-                           xen_pfn_t *arr, int num)
+void *osdep_map_foreign_batch(xc_interface *xch,
+                              uint32_t dom, int prot,
+                              xen_pfn_t *arr, int num)
 {
     int fd = xch->privcmdfd;
     privcmd_mmapbatch_t ioctlx;
     void *addr;
     addr = mmap(NULL, num*XC_PAGE_SIZE, prot, MAP_ANON | MAP_SHARED, -1, 0);
     if ( addr == MAP_FAILED ) {
-        PERROR("xc_map_foreign_batch: mmap failed");
+        PERROR("osdep_map_foreign_batch: mmap failed");
         return NULL;
     }
 
@@ -88,7 +88,7 @@ void *xc_map_foreign_batch(xc_interface *xch,
     if ( ioctl(fd, IOCTL_PRIVCMD_MMAPBATCH, &ioctlx) < 0 )
     {
         int saved_errno = errno;
-        PERROR("xc_map_foreign_batch: ioctl failed");
+        PERROR("osdep_map_foreign_batch: ioctl failed");
         (void)munmap(addr, num*XC_PAGE_SIZE);
         errno = saved_errno;
         return NULL;
diff --git a/tools/libxc/xc_solaris.c b/tools/libxc/xc_solaris.c
index 1e1a0c4..0a0fd14 100644
--- a/tools/libxc/xc_solaris.c
+++ b/tools/libxc/xc_solaris.c
@@ -68,9 +68,9 @@ int osdep_privcmd_close(xc_interface *xch)
     return close(fd);
 }
 
-void *xc_map_foreign_batch(xc_interface *xch,
-                          uint32_t dom, int prot,
-                          xen_pfn_t *arr, int num)
+void *osdep_map_foreign_batch(xc_interface *xch,
+                              uint32_t dom, int prot,
+                              xen_pfn_t *arr, int num)
 {
     int fd = xch->privcmdfd;
     privcmd_mmapbatch_t ioctlx;
diff --git a/tools/libxc/xc_vm_event.c b/tools/libxc/xc_vm_event.c
index a5b3277..4d7e7cc 100644
--- a/tools/libxc/xc_vm_event.c
+++ b/tools/libxc/xc_vm_event.c
@@ -46,6 +46,7 @@ void *xc_vm_event_enable(xc_interface *xch, domid_t domain_id, int param,
     void *ring_page = NULL;
     uint64_t pfn;
     xen_pfn_t ring_pfn, mmap_pfn;
+    int err;
     unsigned int op, mode;
     int rc1, rc2, saved_errno;
 
@@ -73,9 +74,9 @@ void *xc_vm_event_enable(xc_interface *xch, domid_t domain_id, int param,
 
     ring_pfn = pfn;
     mmap_pfn = pfn;
-    ring_page = xc_map_foreign_batch(xch, domain_id, PROT_READ | PROT_WRITE,
-                                     &mmap_pfn, 1);
-    if ( mmap_pfn & XEN_DOMCTL_PFINFO_XTAB )
+    ring_page = xc_map_foreign_bulk(xch, domain_id, PROT_READ | PROT_WRITE,
+				    &mmap_pfn, &err, 1);
+    if ( !ring_page )
     {
         /* Map failed, populate ring page */
         rc1 = xc_domain_populate_physmap_exact(xch, domain_id, 1, 0, 0,
@@ -87,11 +88,11 @@ void *xc_vm_event_enable(xc_interface *xch, domid_t domain_id, int param,
         }
 
         mmap_pfn = ring_pfn;
-        ring_page = xc_map_foreign_batch(xch, domain_id, PROT_READ | PROT_WRITE,
-                                         &mmap_pfn, 1);
-        if ( mmap_pfn & XEN_DOMCTL_PFINFO_XTAB )
+        ring_page = xc_map_foreign_bulk(xch, domain_id, PROT_READ | PROT_WRITE,
+					&mmap_pfn, &err, 1);
+        if ( !ring_page )
         {
-            PERROR("Could not map the ring page\n");
+            PERROR("Could not map the ring page: %d\n", err);
             goto out;
         }
     }
@@ -157,3 +158,13 @@ void *xc_vm_event_enable(xc_interface *xch, domid_t domain_id, int param,
 
     return ring_page;
 }
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/xenmon/xenbaked.c b/tools/xenmon/xenbaked.c
index f092aec..9e2a49b 100644
--- a/tools/xenmon/xenbaked.c
+++ b/tools/xenmon/xenbaked.c
@@ -408,14 +408,15 @@ static struct t_struct *map_tbufs(unsigned long tbufs_mfn, unsigned int num,
                                    + tbufs.t_info->mfn_offset[i];
         int j;
         xen_pfn_t pfn_list[tbufs.t_info->tbuf_size];
+        int err_list[tbufs.t_info->tbuf_size];
 
         for ( j=0; j<tbufs.t_info->tbuf_size; j++)
             pfn_list[j] = (xen_pfn_t)mfn_list[j];
 
-        tbufs.meta[i] = xc_map_foreign_batch(xc_handle, DOMID_XEN,
-                                             PROT_READ | PROT_WRITE,
-                                             pfn_list,
-                                             tbufs.t_info->tbuf_size);
+        tbufs.meta[i] = xc_map_foreign_bulk(xc_handle, DOMID_XEN,
+					    PROT_READ | PROT_WRITE,
+					    pfn_list, err_list,
+					    tbufs.t_info->tbuf_size);
         if ( tbufs.meta[i] == NULL )
         {
             PERROR("Failed to map cpu buffer!");
@@ -1176,3 +1177,13 @@ static int process_record(int cpu, struct t_rec *r)
 
     return 4 + (r->cycles_included ? 8 : 0) + (r->extra_u32 * 4);
 }
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/xenpaging/pagein.c b/tools/xenpaging/pagein.c
index 7cb0f33..18699ec 100644
--- a/tools/xenpaging/pagein.c
+++ b/tools/xenpaging/pagein.c
@@ -23,6 +23,7 @@ static void *page_in(void *arg)
     void *page;
     int i, num;
     xen_pfn_t gfns[XENPAGING_PAGEIN_QUEUE_SIZE];
+    int errs[XENPAGING_PAGEIN_QUEUE_SIZE];
 
     while (1)
     {
@@ -42,7 +43,8 @@ static void *page_in(void *arg)
         pthread_mutex_unlock(&page_in_mutex);
 
         /* Ignore errors */
-        page = xc_map_foreign_pages(pia->xch, pia->dom, PROT_READ, gfns, num);
+        page = xc_map_foreign_bulk(pia->xch, pia->dom, PROT_READ,
+                                   gfns, errs, num);
         if (page)
             munmap(page, PAGE_SIZE * num);
     }
diff --git a/tools/xenpaging/xenpaging.c b/tools/xenpaging/xenpaging.c
index 6776896..a819a5b 100644
--- a/tools/xenpaging/xenpaging.c
+++ b/tools/xenpaging/xenpaging.c
@@ -282,6 +282,7 @@ static struct xenpaging *xenpaging_init(int argc, char *argv[])
     char *p;
     int rc;
     unsigned long ring_pfn, mmap_pfn;
+    int mmap_err;
 
     /* Allocate memory */
     paging = calloc(1, sizeof(struct xenpaging));
@@ -343,8 +344,8 @@ static struct xenpaging *xenpaging_init(int argc, char *argv[])
                         HVM_PARAM_PAGING_RING_PFN, &ring_pfn);
     mmap_pfn = ring_pfn;
     paging->vm_event.ring_page = 
-        xc_map_foreign_batch(xch, paging->vm_event.domain_id, 
-                                PROT_READ | PROT_WRITE, &mmap_pfn, 1);
+        xc_map_foreign_bulk(xch, paging->vm_event.domain_id,
+                            PROT_READ | PROT_WRITE, &mmap_pfn, &mmap_err, 1);
     if ( mmap_pfn & XEN_DOMCTL_PFINFO_XTAB )
     {
         /* Map failed, populate ring page */
@@ -359,11 +360,12 @@ static struct xenpaging *xenpaging_init(int argc, char *argv[])
 
         mmap_pfn = ring_pfn;
         paging->vm_event.ring_page = 
-            xc_map_foreign_batch(xch, paging->vm_event.domain_id, 
-                                    PROT_READ | PROT_WRITE, &mmap_pfn, 1);
+            xc_map_foreign_bulk(xch, paging->vm_event.domain_id,
+                                PROT_READ | PROT_WRITE,
+                                &mmap_pfn, &mmap_err, 1);
         if ( mmap_pfn & XEN_DOMCTL_PFINFO_XTAB )
         {
-            PERROR("Could not map the ring page\n");
+            PERROR("Could not map the ring page: %d\n", mmap_err);
             goto err;
         }
     }
diff --git a/tools/xentrace/xentrace.c b/tools/xentrace/xentrace.c
index c970d42..f66a77c 100644
--- a/tools/xentrace/xentrace.c
+++ b/tools/xentrace/xentrace.c
@@ -504,14 +504,15 @@ static struct t_struct *map_tbufs(unsigned long tbufs_mfn, unsigned int num,
                                    + tbufs.t_info->mfn_offset[i];
         int j;
         xen_pfn_t pfn_list[tbufs.t_info->tbuf_size];
+        int pfn_err[tbufs.t_info->tbuf_size];
 
         for ( j=0; j<tbufs.t_info->tbuf_size; j++)
             pfn_list[j] = (xen_pfn_t)mfn_list[j];
 
-        tbufs.meta[i] = xc_map_foreign_batch(xc_handle, DOMID_XEN,
-                                             PROT_READ | PROT_WRITE,
-                                             pfn_list,
-                                             tbufs.t_info->tbuf_size);
+        tbufs.meta[i] = xc_map_foreign_bulk(xc_handle, DOMID_XEN,
+                                            PROT_READ | PROT_WRITE,
+                                            pfn_list, pfn_err,
+                                            tbufs.t_info->tbuf_size);
         if ( tbufs.meta[i] == NULL )
         {
             PERROR("Failed to map cpu buffer!");
@@ -1221,6 +1222,7 @@ int main(int argc, char **argv)
 
     return ret;
 }
+
 /*
  * Local variables:
  * mode: C
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH XEN v2 13/15] tools: Implement xc_map_foreign_range(s) in terms of common helper
  2015-07-15 15:46 [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries Ian Campbell
                   ` (11 preceding siblings ...)
  2015-07-15 15:47 ` [PATCH XEN v2 12/15] tools: Remove xc_map_foreign_batch Ian Campbell
@ 2015-07-15 15:47 ` Ian Campbell
  2015-07-15 15:47 ` [PATCH XEN v2 14/15] tools: Refactor foreign memory mapping into libxenforeignmemory Ian Campbell
                   ` (14 subsequent siblings)
  27 siblings, 0 replies; 55+ messages in thread
From: Ian Campbell @ 2015-07-15 15:47 UTC (permalink / raw)
  To: ian.jackson, wei.liu2, xen-devel
  Cc: roger.pau, Ian Campbell, stefano.stabellini

Both Linux and FreeBSD already implemented these functions using
identical helpers based on xc_map_foreign_pages. Make one copy of
these common helpers and switch all OSes to use them, even those which
previously had a specific lower level implementation of this
functionality.

This is makes two fewer low level interfaces to think about.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
---
 docs/misc/toolstack-library-abis.pandoc | 35 +++++------------
 tools/libxc/xc_foreign_memory.c         | 50 +++++++++++++++++++++++
 tools/libxc/xc_freebsd_osdep.c          | 50 -----------------------
 tools/libxc/xc_linux_osdep.c            | 49 -----------------------
 tools/libxc/xc_minios.c                 | 43 --------------------
 tools/libxc/xc_netbsd.c                 | 70 ---------------------------------
 tools/libxc/xc_solaris.c                | 67 -------------------------------
 7 files changed, 60 insertions(+), 304 deletions(-)

diff --git a/docs/misc/toolstack-library-abis.pandoc b/docs/misc/toolstack-library-abis.pandoc
index 4ad6c7d..35674cc 100644
--- a/docs/misc/toolstack-library-abis.pandoc
+++ b/docs/misc/toolstack-library-abis.pandoc
@@ -876,36 +876,25 @@ functionality areas:
 
 # Foreign memory mapping functions
 
-The `xc_map_foreign_*` functions are a bit of a twisty maze.
+The `xc_map_foreign_*` functions were once a bit of a twisty maze, but
+now all are implemented in terms of a single underlying per-OS
+function.
 
 osdep level interfaces:
 
 Interface            Linux Minios Netbsd Freebsd Solaris
 -------------------- ----- ------ ------ ------- -------
 `map_foreign_bulk`   Y     Y      compat Y       compat
-`map_foreign_range`  Y     Y      Y      Y       Y
-`map_foreign_ranges` Y     Y      Y      Y       Y
 
-_compat_ means using `xc_map_foreign_bulk_compat`
-
-`xc_map_foreign_pages` is common and implemented using
-`xc_map_foreign_bulk`.
-
-Some osdep call other `xc_map_foreign_*` recursivley:
-
-Interface            Linux                        FreeBSD
--------------------- ---------------------------- -------------------------
-`map_foreign_bulk`   `IOCTL_PRIVCMD_MMAPBATCH_V2` `IOCTL_PRIVCMD_MMAPBATCH`
-`map_foreign_range`  `xc_map_foreign_pages`       `xc_map_foreign_pages`
-`map_foreign_ranges` `xc_map_foreign_pages`       `xc_map_foreign_pages`
+_compat_ means using `osdep_map_foreign_batch` layer
 
 libxenctrl level interfaces:
 
 Interface               Underlying interface
 ----------------------  ---------------------------
 `xc_map_foreign_pages`  `xc_map_foreign_bulk`
-`xc_map_foreign_range`  `osdep: map_foreign_range`
-`xc_map_foreign_ranges` `osdep: map_foreign_ranges`
+`xc_map_foreign_range`  `xc_map_foreign_pages`
+`xc_map_foreign_ranges` `xc_map_foreign_pages`
 `xc_map_foreign_bulk`   `osdep: map_foreign_bulk`
 
 `osdep: *` have been collapsed since osdep layer was removed.
@@ -915,17 +904,13 @@ which have not implemented their own version. It used to use
 `xc_map_foreign_batch` which is now an osdep for those OSes which need
 it.
 
-Interface               Internal users               External users
-----------------------  --------------               --------------
+Interface               In-tree users                External users
+----------------------  -------------                --------------
 `xc_map_foreign_pages`  xenpaging                    qemu-pv
 `xc_map_foreign_range`  xenconsole, kdd, libxl,      qemu-dm, qemu-pv
                         mfndump, memshrtool, xenmon,
                         xenstored, xentrace
-`xc_map_foreign_ranges` NONE
+`xc_map_foreign_ranges` libxc internal
 `xc_map_foreign_bulk`   used recursively             qemu-dm
 
-Only one interface should become a stable API. Something based on
-`xc_map_foreign_bulk` seems most appropriate (it is used by
-`xc_map_foreign_pages` as well as by xc_map_foreign_range` and
-`xc_map_foreign_ranges` on Linux + FreeBSD. A compat version exists in
-terms of `xc_map_foreign_batch` for other OSes.
+`xc_map_foreign_bulk` should become an underlying stable API.
diff --git a/tools/libxc/xc_foreign_memory.c b/tools/libxc/xc_foreign_memory.c
index ae133a1..c96489d 100644
--- a/tools/libxc/xc_foreign_memory.c
+++ b/tools/libxc/xc_foreign_memory.c
@@ -51,6 +51,56 @@ void *xc_map_foreign_pages(xc_interface *xch, uint32_t dom, int prot,
     return res;
 }
 
+void *xc_map_foreign_range(xc_interface *xch,
+                           uint32_t dom, int size, int prot,
+                           unsigned long mfn)
+{
+    xen_pfn_t *arr;
+    int num;
+    int i;
+    void *ret;
+
+    num = (size + XC_PAGE_SIZE - 1) >> XC_PAGE_SHIFT;
+    arr = calloc(num, sizeof(xen_pfn_t));
+    if ( arr == NULL )
+        return NULL;
+
+    for ( i = 0; i < num; i++ )
+        arr[i] = mfn + i;
+
+    ret = xc_map_foreign_pages(xch, dom, prot, arr, num);
+    free(arr);
+    return ret;
+}
+
+void *xc_map_foreign_ranges(xc_interface *xch,
+                            uint32_t dom, size_t size,
+                            int prot, size_t chunksize,
+                            privcmd_mmap_entry_t entries[],
+                            int nentries)
+{
+    xen_pfn_t *arr;
+    int num_per_entry;
+    int num;
+    int i;
+    int j;
+    void *ret;
+
+    num_per_entry = chunksize >> XC_PAGE_SHIFT;
+    num = num_per_entry * nentries;
+    arr = calloc(num, sizeof(xen_pfn_t));
+    if ( arr == NULL )
+        return NULL;
+
+    for ( i = 0; i < nentries; i++ )
+        for ( j = 0; j < num_per_entry; j++ )
+            arr[i * num_per_entry + j] = entries[i].mfn + j;
+
+    ret = xc_map_foreign_pages(xch, dom, prot, arr, num);
+    free(arr);
+    return ret;
+}
+
 /*
  * stub for all not yet converted OSes (NetBSD and Solaris). New OSes should
  * just implement xc_map_foreign_bulk.
diff --git a/tools/libxc/xc_freebsd_osdep.c b/tools/libxc/xc_freebsd_osdep.c
index b0ec965..d09e0da 100644
--- a/tools/libxc/xc_freebsd_osdep.c
+++ b/tools/libxc/xc_freebsd_osdep.c
@@ -126,56 +126,6 @@ void *xc_map_foreign_bulk(xc_interface *xch,
     return addr;
 }
 
-void *xc_map_foreign_range(xc_interface *xch,
-                           uint32_t dom, int size, int prot,
-                           unsigned long mfn)
-{
-    xen_pfn_t *arr;
-    int num;
-    int i;
-    void *ret;
-
-    num = (size + XC_PAGE_SIZE - 1) >> XC_PAGE_SHIFT;
-    arr = calloc(num, sizeof(xen_pfn_t));
-    if ( arr == NULL )
-        return NULL;
-
-    for ( i = 0; i < num; i++ )
-        arr[i] = mfn + i;
-
-    ret = xc_map_foreign_pages(xch, dom, prot, arr, num);
-    free(arr);
-    return ret;
-}
-
-void *xc_map_foreign_ranges(xc_interface *xch,
-                            uint32_t dom, size_t size,
-                            int prot, size_t chunksize,
-                            privcmd_mmap_entry_t entries[],
-                            int nentries)
-{
-    xen_pfn_t *arr;
-    int num_per_entry;
-    int num;
-    int i;
-    int j;
-    void *ret;
-
-    num_per_entry = chunksize >> XC_PAGE_SHIFT;
-    num = num_per_entry * nentries;
-    arr = calloc(num, sizeof(xen_pfn_t));
-    if ( arr == NULL )
-        return NULL;
-
-    for ( i = 0; i < nentries; i++ )
-        for ( j = 0; j < num_per_entry; j++ )
-            arr[i * num_per_entry + j] = entries[i].mfn + j;
-
-    ret = xc_map_foreign_pages(xch, dom, prot, arr, num);
-    free(arr);
-    return ret;
-}
-
 /*
  * Local variables:
  * mode: C
diff --git a/tools/libxc/xc_linux_osdep.c b/tools/libxc/xc_linux_osdep.c
index 6641bd1..9f8805a 100644
--- a/tools/libxc/xc_linux_osdep.c
+++ b/tools/libxc/xc_linux_osdep.c
@@ -285,55 +285,6 @@ void *xc_map_foreign_bulk(xc_interface *xch,
     return addr;
 }
 
-void *xc_map_foreign_range(xc_interface *xch,
-                           uint32_t dom, int size, int prot,
-                           unsigned long mfn)
-{
-    xen_pfn_t *arr;
-    int num;
-    int i;
-    void *ret;
-
-    num = (size + XC_PAGE_SIZE - 1) >> XC_PAGE_SHIFT;
-    arr = calloc(num, sizeof(xen_pfn_t));
-    if ( arr == NULL )
-        return NULL;
-
-    for ( i = 0; i < num; i++ )
-        arr[i] = mfn + i;
-
-    ret = xc_map_foreign_pages(xch, dom, prot, arr, num);
-    free(arr);
-    return ret;
-}
-
-void *xc_map_foreign_ranges(xc_interface *xch,
-                            uint32_t dom, size_t size, int prot,
-                            size_t chunksize, privcmd_mmap_entry_t entries[],
-                            int nentries)
-{
-    xen_pfn_t *arr;
-    int num_per_entry;
-    int num;
-    int i;
-    int j;
-    void *ret;
-
-    num_per_entry = chunksize >> XC_PAGE_SHIFT;
-    num = num_per_entry * nentries;
-    arr = calloc(num, sizeof(xen_pfn_t));
-    if ( arr == NULL )
-        return NULL;
-
-    for ( i = 0; i < nentries; i++ )
-        for ( j = 0; j < num_per_entry; j++ )
-            arr[i * num_per_entry + j] = entries[i].mfn + j;
-
-    ret = xc_map_foreign_pages(xch, dom, prot, arr, num);
-    free(arr);
-    return ret;
-}
-
 /*
  * Local variables:
  * mode: C
diff --git a/tools/libxc/xc_minios.c b/tools/libxc/xc_minios.c
index ed20652..1616c58 100644
--- a/tools/libxc/xc_minios.c
+++ b/tools/libxc/xc_minios.c
@@ -74,49 +74,6 @@ void *xc_map_foreign_bulk(xc_interface *xch,
     return map_frames_ex(arr, num, 1, 0, 1, dom, err, pt_prot);
 }
 
-void *xc_map_foreign_range(xc_interface *xch,
-                           uint32_t dom,
-                           int size, int prot,
-                           unsigned long mfn)
-{
-    unsigned long pt_prot = 0;
-
-    if (prot & PROT_READ)
-	pt_prot = L1_PROT_RO;
-    if (prot & PROT_WRITE)
-	pt_prot = L1_PROT;
-
-    assert(!(size % getpagesize()));
-    return map_frames_ex(&mfn, size / getpagesize(), 0, 1, 1, dom, NULL, pt_prot);
-}
-
-void *xc_map_foreign_ranges(xc_interface *xch,
-                            uint32_t dom,
-                            size_t size, int prot, size_t chunksize,
-                            privcmd_mmap_entry_t entries[], int nentries)
-{
-    unsigned long *mfns;
-    int i, j, n;
-    unsigned long pt_prot = 0;
-    void *ret;
-
-    if (prot & PROT_READ)
-	pt_prot = L1_PROT_RO;
-    if (prot & PROT_WRITE)
-	pt_prot = L1_PROT;
-
-    mfns = malloc((size / XC_PAGE_SIZE) * sizeof(*mfns));
-
-    n = 0;
-    for (i = 0; i < nentries; i++)
-        for (j = 0; j < chunksize / XC_PAGE_SIZE; j++)
-            mfns[n++] = entries[i].mfn + j;
-
-    ret = map_frames_ex(mfns, n, 1, 0, 1, dom, NULL, pt_prot);
-    free(mfns);
-    return ret;
-}
-
 /* Optionally flush file to disk and discard page cache */
 void discard_file_cache(xc_interface *xch, int fd, int flush)
 {
diff --git a/tools/libxc/xc_netbsd.c b/tools/libxc/xc_netbsd.c
index f02015c..2654d18 100644
--- a/tools/libxc/xc_netbsd.c
+++ b/tools/libxc/xc_netbsd.c
@@ -97,76 +97,6 @@ void *osdep_map_foreign_batch(xc_interface *xch,
 
 }
 
-void *xc_map_foreign_range(xc_interface *xch,
-                           uint32_t dom,
-                           int size, int prot,
-                           unsigned long mfn)
-{
-    int fd = xch->privcmdfd;
-    privcmd_mmap_t ioctlx;
-    privcmd_mmap_entry_t entry;
-    void *addr;
-    addr = mmap(NULL, size, prot, MAP_ANON | MAP_SHARED, -1, 0);
-    if ( addr == MAP_FAILED ) {
-        PERROR("xc_map_foreign_range: mmap failed");
-        return NULL;
-    }
-
-    ioctlx.num=1;
-    ioctlx.dom=dom;
-    ioctlx.entry=&entry;
-    entry.va=(unsigned long) addr;
-    entry.mfn=mfn;
-    entry.npages=(size+XC_PAGE_SIZE-1)>>XC_PAGE_SHIFT;
-    if ( ioctl(fd, IOCTL_PRIVCMD_MMAP, &ioctlx) < 0 )
-    {
-        int saved_errno = errno;
-        PERROR("xc_map_foreign_range: ioctl failed");
-        (void)munmap(addr, size);
-        errno = saved_errno;
-        return NULL;
-    }
-    return addr;
-}
-
-void *xc_map_foreign_ranges(xc_interface *xch,
-                            uint32_t dom,
-                            size_t size, int prot, size_t chunksize,
-                            privcmd_mmap_entry_t entries[], int nentries)
-{
-    int fd = xch->privcmdfd;
-	privcmd_mmap_t ioctlx;
-	int i, rc;
-	void *addr;
-
-	addr = mmap(NULL, size, prot, MAP_ANON | MAP_SHARED, -1, 0);
-	if (addr == MAP_FAILED)
-		goto mmap_failed;
-
-	for (i = 0; i < nentries; i++) {
-		entries[i].va = (uintptr_t)addr + (i * chunksize);
-		entries[i].npages = chunksize >> XC_PAGE_SHIFT;
-	}
-
-	ioctlx.num   = nentries;
-	ioctlx.dom   = dom;
-	ioctlx.entry = entries;
-
-	rc = ioctl(fd, IOCTL_PRIVCMD_MMAP, &ioctlx);
-	if (rc)
-		goto ioctl_failed;
-
-	return addr;
-
-ioctl_failed:
-	rc = munmap(addr, size);
-	if (rc == -1)
-		ERROR("%s: error in error path\n", __FUNCTION__);
-
-mmap_failed:
-	return NULL;
-}
-
 /* Optionally flush file to disk and discard page cache */
 void discard_file_cache(xc_interface *xch, int fd, int flush) 
 {
diff --git a/tools/libxc/xc_solaris.c b/tools/libxc/xc_solaris.c
index 0a0fd14..e1e126d 100644
--- a/tools/libxc/xc_solaris.c
+++ b/tools/libxc/xc_solaris.c
@@ -95,73 +95,6 @@ void *osdep_map_foreign_batch(xc_interface *xch,
 
 }
 
-void *xc_map_foreign_range(xc_interface *xch,
-                           uint32_t dom,
-                           int size, int prot,
-                           unsigned long mfn)
-{
-    int fd = xch->privcmdfd;
-    privcmd_mmap_t ioctlx;
-    privcmd_mmap_entry_t entry;
-    void *addr;
-    addr = mmap(NULL, size, prot, MAP_SHARED, fd, 0);
-    if ( addr == MAP_FAILED )
-        return NULL;
-
-    ioctlx.num=1;
-    ioctlx.dom=dom;
-    ioctlx.entry=&entry;
-    entry.va=(unsigned long) addr;
-    entry.mfn=mfn;
-    entry.npages=(size+XC_PAGE_SIZE-1)>>XC_PAGE_SHIFT;
-    if ( ioctl(fd, IOCTL_PRIVCMD_MMAP, &ioctlx) < 0 )
-    {
-        int saved_errno = errno;
-        (void)munmap(addr, size);
-        errno = saved_errno;
-        return NULL;
-    }
-    return addr;
-}
-
-void *xc_map_foreign_ranges(xc_interface *xch,
-                            uint32_t dom,
-                            size_t size, int prot, size_t chunksize,
-                            privcmd_mmap_entry_t entries[], int nentries)
-{
-    int fd = xch->privcmdfd;
-    privcmd_mmap_t ioctlx;
-    int i, rc;
-    void *addr;
-
-    addr = mmap(NULL, size, prot, MAP_SHARED, fd, 0);
-    if (addr == MAP_FAILED)
-        goto mmap_failed;
-
-    for (i = 0; i < nentries; i++) {
-        entries[i].va = (uintptr_t)addr + (i * chunksize);
-        entries[i].npages = chunksize >> XC_PAGE_SHIFT;
-    }
-
-    ioctlx.num   = nentries;
-    ioctlx.dom   = dom;
-    ioctlx.entry = entries;
-
-    rc = ioctl(fd, IOCTL_PRIVCMD_MMAP, &ioctlx);
-    if (rc)
-        goto ioctl_failed;
-
-    return addr;
-
-ioctl_failed:
-    rc = munmap(addr, size);
-    if (rc == -1)
-        PERROR("%s: error in error path", __FUNCTION__);
-
-mmap_failed:
-    return NULL;
-}
-
 /* Optionally flush file to disk and discard page cache */
 void discard_file_cache(xc_interface *xch, int fd, int flush) 
 {
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH XEN v2 14/15] tools: Refactor foreign memory mapping into libxenforeignmemory
  2015-07-15 15:46 [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries Ian Campbell
                   ` (12 preceding siblings ...)
  2015-07-15 15:47 ` [PATCH XEN v2 13/15] tools: Implement xc_map_foreign_range(s) in terms of common helper Ian Campbell
@ 2015-07-15 15:47 ` Ian Campbell
  2015-07-15 15:47 ` [PATCH XEN v2 15/15] HACK: Add a .config to pull all the right bits Ian Campbell
                   ` (13 subsequent siblings)
  27 siblings, 0 replies; 55+ messages in thread
From: Ian Campbell @ 2015-07-15 15:47 UTC (permalink / raw)
  To: ian.jackson, wei.liu2, xen-devel
  Cc: roger.pau, Ian Campbell, stefano.stabellini

libxenforeignmemory will provide a stable API and ABI for mapping
foreign domain memory (subject to appropriate privileges).

The new library exposes an interface equivalent to
xc_map_foreign_memory_bulk, which all the other
xc_map_foreign_memory_* functions (which remain in libxc) are
implemented in terms of.

Upon request (via #define XC_WANT_COMPAT_MAP_FOREIGN_API) libxenctrl
will provide a compat API for the old names. This is used by qemu-xen
and qemu-trad as well as various in tree things (which required
de-dupping various #includes in some too to get the #define before the
first).

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
---
Must be applied with:
  - "qemu-xen-traditional: qemu-xen-traditional: Add
    libxenforeignmemory to rpath-link" and a corresponding QEMU_TAG
    update folded here.
  - "mini-os: mini-os: Include libxenforeignmemory with libxc" and a
    corresponding bump to MINIOS_UPSTREAM_REVISION folded in here.
---
 .gitignore                                         |   2 +
 docs/misc/toolstack-library-abis.pandoc            |  22 +-
 stubdom/Makefile                                   |  21 +-
 tools/Makefile                                     |   3 +
 tools/Rules.mk                                     |  11 +-
 tools/console/daemon/utils.c                       |   1 -
 tools/console/daemon/utils.h                       |   1 +
 tools/libxc/Makefile                               |   8 +-
 tools/libxc/include/xenctrl.h                      |  26 --
 tools/libxc/include/xenctrl_compat.h               |  36 +++
 tools/libxc/xc_domain_restore.c                    |   4 +-
 tools/libxc/xc_domain_save.c                       |   4 +-
 tools/libxc/xc_foreign_memory.c                    |  49 +---
 tools/libxc/xc_freebsd_osdep.c                     | 137 ----------
 tools/libxc/xc_linux_osdep.c                       | 296 ---------------------
 tools/libxc/xc_minios.c                            |  29 --
 tools/libxc/xc_netbsd.c                            |  73 -----
 tools/libxc/xc_private.c                           |  13 +-
 tools/libxc/xc_private.h                           |  11 +-
 tools/libxc/xc_solaris.c                           |  73 -----
 tools/libxc/xc_sr_restore.c                        |   4 +-
 tools/libxc/xc_sr_save.c                           |   4 +-
 tools/libxc/xc_vm_event.c                          |  10 +-
 tools/libxc/xg_private.h                           |   3 +-
 tools/libxenforeignmemory/Makefile                 |  67 +++++
 tools/libxenforeignmemory/compat.c                 |  72 +++++
 tools/libxenforeignmemory/core.c                   |  65 +++++
 tools/libxenforeignmemory/freebsd.c                | 126 +++++++++
 .../libxenforeignmemory/include/xenforeignmemory.h |  68 +++++
 tools/libxenforeignmemory/libxenforeignmemory.map  |   7 +
 tools/libxenforeignmemory/linux.c                  | 284 ++++++++++++++++++++
 tools/libxenforeignmemory/minios.c                 |  59 ++++
 tools/libxenforeignmemory/netbsd.c                 |  92 +++++++
 tools/libxenforeignmemory/private.h                |  47 ++++
 tools/libxenforeignmemory/solaris.c                |  95 +++++++
 tools/libxl/libxl_internal.h                       |   1 +
 tools/misc/xen-mfndump.c                           |   1 +
 tools/ocaml/libs/xc/xenctrl_stubs.c                |   1 +
 tools/python/xen/lowlevel/xc/xc.c                  |   2 +-
 tools/xenmon/xenbaked.c                            |   1 +
 tools/xenpaging/pagein.c                           |   1 -
 tools/xenpaging/xenpaging.c                        |   1 -
 tools/xenpaging/xenpaging.h                        |   2 +
 tools/xenstore/xenstored_core.c                    |   1 -
 tools/xenstore/xenstored_core.h                    |   1 +
 tools/xentrace/xenctx.c                            |   3 +-
 tools/xentrace/xentrace.c                          |   1 +
 47 files changed, 1118 insertions(+), 721 deletions(-)
 delete mode 100644 tools/libxc/xc_freebsd_osdep.c
 delete mode 100644 tools/libxc/xc_linux_osdep.c
 create mode 100644 tools/libxenforeignmemory/Makefile
 create mode 100644 tools/libxenforeignmemory/compat.c
 create mode 100644 tools/libxenforeignmemory/core.c
 create mode 100644 tools/libxenforeignmemory/freebsd.c
 create mode 100644 tools/libxenforeignmemory/include/xenforeignmemory.h
 create mode 100644 tools/libxenforeignmemory/libxenforeignmemory.map
 create mode 100644 tools/libxenforeignmemory/linux.c
 create mode 100644 tools/libxenforeignmemory/minios.c
 create mode 100644 tools/libxenforeignmemory/netbsd.c
 create mode 100644 tools/libxenforeignmemory/private.h
 create mode 100644 tools/libxenforeignmemory/solaris.c

diff --git a/.gitignore b/.gitignore
index 5841570..bb643f7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -63,6 +63,7 @@ stubdom/libxentoollog-*
 stubdom/libxenevtchn-*
 stubdom/libxengnttab-*
 stubdom/libxencall-*
+stubdom/libxenforeignmemory-*
 stubdom/libxc-*
 stubdom/lwip-*
 stubdom/mini-os-*
@@ -93,6 +94,7 @@ tools/libxentoollog/headers.chk
 tools/libxenevtchn/headers.chk
 tools/libxengnttab/headers.chk
 tools/libxencall/headers.chk
+tools/libxenforeignmemory/headers.chk
 tools/blktap2/daemon/blktapctrl
 tools/blktap2/drivers/img2qcow
 tools/blktap2/drivers/lock-util
diff --git a/docs/misc/toolstack-library-abis.pandoc b/docs/misc/toolstack-library-abis.pandoc
index 35674cc..63b83bc 100644
--- a/docs/misc/toolstack-library-abis.pandoc
+++ b/docs/misc/toolstack-library-abis.pandoc
@@ -166,6 +166,16 @@ Interface                         Underlying interface           Known external
 `xencall_free_buffer`             `xencall_free_buffer_pages`
 `xencall_free_buffer_pages`       `munmap(2)`, `madvise(2)`
 
+## `libxenforeignmemory`: privileged foreign mappings
+
+Mapping foreign guest memory.
+
+Interface                         Underlying interface           Known external users
+--------------------------------- ------------------------------ --------------------
+`xenforeignmemory_open`           `open(2)`
+`xenforeignmemory_close`          `close(2)`
+`xenforeignmemory_map`            `IOCTL_PRIVCMD_MMAPBATCH` etc
+
 # Unstable libraries
 
 These libraries do not provide a stable interface and are required to
@@ -269,12 +279,14 @@ The following are private:
 
 ### Mapping foreign memory
 
-Interface                         Underlying interface           Known external users
---------------------------------- ------------------------------ --------------------
-`xc_map_foreign_pages`            `IOCTL_PRIVCMD_MMAP...`        qemu-pv
-`xc_map_foreign_range`            `IOCTL_PRIVCMD_MMAP...`        qemu-dm, and qemu-pv
+All implemented in terms of `xenforeignmemory_map`.
+
+Interface                         Known external users
+--------------------------------- --------------------
+`xc_map_foreign_pages`            qemu-pv
+`xc_map_foreign_range`            qemu-dm, qemu-pv
 `xc_map_foreign_ranges`
-`xc_map_foreign_bulk`             `IOCTL_PRIVCMD_MMAPBATCH_V2`   qemu-dm
+`xc_map_foreign_bulk`             qemu-dm
 
 ### Managing guest memory map
 
diff --git a/stubdom/Makefile b/stubdom/Makefile
index ec058ca..529f5c3 100644
--- a/stubdom/Makefile
+++ b/stubdom/Makefile
@@ -336,6 +336,12 @@ mk-headers-$(XEN_TARGET_ARCH): $(IOEMU_LINKFARM_TARGET)
 	  ln -sf $(XEN_ROOT)/tools/libxencall/include/*.h include/ && \
 	  ln -sf $(XEN_ROOT)/tools/libxencall/*.c . && \
 	  ln -sf $(XEN_ROOT)/tools/libxencall/Makefile . )
+	mkdir -p libxenforeignmemory-$(XEN_TARGET_ARCH)/include
+	[ -h libxenforeignmemory-$(XEN_TARGET_ARCH)/Makefile ] || ( cd libxenforeignmemory-$(XEN_TARGET_ARCH) && \
+	  ln -sf $(XEN_ROOT)/tools/libxenforeignmemory/*.h . && \
+	  ln -sf $(XEN_ROOT)/tools/libxenforeignmemory/include/*.h include/ && \
+	  ln -sf $(XEN_ROOT)/tools/libxenforeignmemory/*.c . && \
+	  ln -sf $(XEN_ROOT)/tools/libxenforeignmemory/Makefile . )
 	mkdir -p libxc-$(XEN_TARGET_ARCH)
 	[ -h libxc-$(XEN_TARGET_ARCH)/Makefile ] || ( cd libxc-$(XEN_TARGET_ARCH) && \
 	  ln -sf $(XEN_ROOT)/tools/libxc/*.h . && \
@@ -390,6 +396,7 @@ libxengnttab-$(XEN_TARGET_ARCH)/libxengnttab.a: $(NEWLIB_STAMPFILE)
 	$(MAKE) -C $(XEN_ROOT)/tools/include
 	$(MAKE) DESTDIR= -C $(MINI_OS) links
 	CPPFLAGS="$(TARGET_CPPFLAGS)" CFLAGS="$(TARGET_CFLAGS)" $(MAKE) DESTDIR= -C libxengnttab-$(XEN_TARGET_ARCH)
+APP_LDLIBS += -L$(XEN_ROOT)/stubdom/libxencall-$(MINIOS_TARGET_ARCH) -whole-archive -lxencall -no-whole-archive
 
 #######
 # libxencall
@@ -401,6 +408,18 @@ libxencall-$(XEN_TARGET_ARCH)/libxencall.a: $(NEWLIB_STAMPFILE)
 	$(MAKE) -C $(XEN_ROOT)/tools/include
 	$(MAKE) DESTDIR= -C $(MINI_OS) links
 	CPPFLAGS="$(TARGET_CPPFLAGS)" CFLAGS="$(TARGET_CFLAGS)" $(MAKE) DESTDIR= -C libxencall-$(XEN_TARGET_ARCH)
+APP_LDLIBS += -L$(XEN_ROOT)/stubdom/libxencall-$(MINIOS_TARGET_ARCH) -whole-archive -lxencall -no-whole-archive
+
+#######
+# libxenforeignmemory
+#######
+
+.PHONY: libxenforeignmemory
+libxenforeignmemory: libxenforeignmemory-$(XEN_TARGET_ARCH)/libxenforeignmemory.a
+libxenforeignmemory-$(XEN_TARGET_ARCH)/libxenforeignmemory.a: $(NEWLIB_STAMPFILE)
+	$(MAKE) -C $(XEN_ROOT)/tools/include
+	$(MAKE) DESTDIR= -C $(MINI_OS) links
+	CPPFLAGS="$(TARGET_CPPFLAGS)" CFLAGS="$(TARGET_CFLAGS)" $(MAKE) DESTDIR= -C libxenforeignmemory-$(XEN_TARGET_ARCH)
 
 #######
 # libxc
@@ -408,7 +427,7 @@ libxencall-$(XEN_TARGET_ARCH)/libxencall.a: $(NEWLIB_STAMPFILE)
 
 .PHONY: libxc
 libxc: libxc-$(XEN_TARGET_ARCH)/libxenctrl.a libxc-$(XEN_TARGET_ARCH)/libxenguest.a
-libxc-$(XEN_TARGET_ARCH)/libxenctrl.a: libxentoollog libxenevtchn libxengnttab libxencall cross-zlib
+libxc-$(XEN_TARGET_ARCH)/libxenctrl.a: libxentoollog libxenevtchn libxengnttab libxencall libxenforeignmemory cross-zlib
 	$(MAKE) -C $(XEN_ROOT)/tools/include
 	$(MAKE) DESTDIR= -C $(MINI_OS) links
 	CPPFLAGS="$(TARGET_CPPFLAGS)" CFLAGS="$(TARGET_CFLAGS)" $(MAKE) DESTDIR= CONFIG_LIBXC_MINIOS=y -C libxc-$(XEN_TARGET_ARCH)
diff --git a/tools/Makefile b/tools/Makefile
index e5c8879..30abd57 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -7,6 +7,7 @@ SUBDIRS-y += libxentoollog
 SUBDIRS-y += libxenevtchn
 SUBDIRS-y += libxengnttab
 SUBDIRS-y += libxencall
+SUBDIRS-y += libxenforeignmemory
 SUBDIRS-y += libxc
 SUBDIRS-$(FLASK_ENABLE) += flask
 SUBDIRS-y += xenstore
@@ -253,6 +254,7 @@ subdir-all-qemu-xen-dir: qemu-xen-dir-find
 		--source-path=$$source \
 		--extra-cflags="-DXC_WANT_COMPAT_EVTCHN_API=1 \
 		-DXC_WANT_COMPAT_GNTTAB_API=1 \
+		-DXC_WANT_COMPAT_MAP_FOREIGN_API=1 \
 		-I$(XEN_ROOT)/tools/include \
 		-I$(XEN_ROOT)/tools/libxentoollog/include \
 		-I$(XEN_ROOT)/tools/libxenevtchn/include \
@@ -267,6 +269,7 @@ subdir-all-qemu-xen-dir: qemu-xen-dir-find
 		-Wl,-rpath-link=$(XEN_ROOT)/tools/libxenevtchn \
 		-Wl,-rpath-link=$(XEN_ROOT)/tools/libxengnttab \
 		-Wl,-rpath-link=$(XEN_ROOT)/tools/libxencall \
+		-Wl,-rpath-link=$(XEN_ROOT)/tools/libxenforeignmemory \
 		$(QEMU_UPSTREAM_RPATH)" \
 		--bindir=$(LIBEXEC_BIN) \
 		--datadir=$(SHAREDIR)/qemu-xen \
diff --git a/tools/Rules.mk b/tools/Rules.mk
index 405a6a5..4a67f1f 100644
--- a/tools/Rules.mk
+++ b/tools/Rules.mk
@@ -14,6 +14,7 @@ XEN_LIBXENTOOLLOG  = $(XEN_ROOT)/tools/libxentoollog
 XEN_LIBXENEVTCHN   = $(XEN_ROOT)/tools/libxenevtchn
 XEN_LIBXENGNTTAB   = $(XEN_ROOT)/tools/libxengnttab
 XEN_LIBXENCALL     = $(XEN_ROOT)/tools/libxencall
+XEN_LIBXENFOREIGNMEMORY = $(XEN_ROOT)/tools/libxenforeignmemory
 XEN_LIBXC          = $(XEN_ROOT)/tools/libxc
 XEN_XENLIGHT       = $(XEN_ROOT)/tools/libxl
 XEN_XENSTORE       = $(XEN_ROOT)/tools/xenstore
@@ -103,12 +104,16 @@ CFLAGS_libxencall = -I$(XEN_LIBXENCALL)/include $(CFLAGS_xeninclude)
 LDLIBS_libxencall = $(XEN_LIBXENCALL)/libxencall$(libextension)
 SHLIB_libxencall  = -Wl,-rpath-link=$(XEN_LIBXENCALL)
 
-CFLAGS_libxenctrl = -I$(XEN_LIBXC)/include $(CFLAGS_libxentoollog) $(CFLAGS_xeninclude)
-SHDEPS_libxenctrl = $(SHLIB_libxentoollog) $(SHLIB_libxenevtchn) $(SHLIB_libxengnttab) $(SHLIB_libxengntshr) $(SHLIB_libxencall)
+CFLAGS_libxenforeignmemory = -I$(XEN_LIBXENFOREIGNMEMORY)/include $(CFLAGS_xeninclude)
+LDLIBS_libxenforeignmemory = $(XEN_LIBXENFOREIGNMEMORY)/libxenforeignmemory$(libextension)
+SHLIB_libxenforeignmemory  = -Wl,-rpath-link=$(XEN_LIBXENFOREIGNMEMORY)
+
+CFLAGS_libxenctrl = -I$(XEN_LIBXC)/include $(CFLAGS_libxentoollog) $(CFLAGS_libxenforeignmemory) $(CFLAGS_xeninclude)
+SHDEPS_libxenctrl = $(SHLIB_libxentoollog) $(SHLIB_libxenevtchn) $(SHLIB_libxengnttab) $(SHLIB_libxengntshr) $(SHLIB_libxencall) $(SHLIB_libxenforeignmemory)
 LDLIBS_libxenctrl = $(SHDEPS_libxenctrl) $(XEN_LIBXC)/libxenctrl$(libextension)
 SHLIB_libxenctrl  = $(SHDEPS_libxenctrl) -Wl,-rpath-link=$(XEN_LIBXC)
 
-CFLAGS_libxenguest = -I$(XEN_LIBXC)/include $(CFLAGS_libxenevtchn) $(CFLAGS_xeninclude)
+CFLAGS_libxenguest = -I$(XEN_LIBXC)/include $(CFLAGS_libxenevtchn) $(CFLAGS_libxenforeignmemory) $(CFLAGS_xeninclude)
 SHDEPS_libxenguest = $(SHLIB_libxenevtchn)
 LDLIBS_libxenguest = $(SHDEPS_libxenguest) $(XEN_LIBXC)/libxenguest$(libextension)
 SHLIB_libxenguest  = $(SHDEPS_libxenguest) -Wl,-rpath-link=L$(XEN_LIBXC)
diff --git a/tools/console/daemon/utils.c b/tools/console/daemon/utils.c
index 71dd185..edc1595 100644
--- a/tools/console/daemon/utils.c
+++ b/tools/console/daemon/utils.c
@@ -34,7 +34,6 @@
 #include <string.h>
 #include <signal.h>
 
-#include "xenctrl.h"
 #include "utils.h"
 
 struct xs_handle *xs;
diff --git a/tools/console/daemon/utils.h b/tools/console/daemon/utils.h
index 8725dcd..45c7c34 100644
--- a/tools/console/daemon/utils.h
+++ b/tools/console/daemon/utils.h
@@ -24,6 +24,7 @@
 #include <stdbool.h>
 #include <syslog.h>
 #include <stdio.h>
+#define XC_WANT_COMPAT_MAP_FOREIGN_API
 #include <xenctrl.h>
 
 #include <xenstore.h>
diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile
index 42fbabe..79afb78 100644
--- a/tools/libxc/Makefile
+++ b/tools/libxc/Makefile
@@ -41,8 +41,8 @@ CTRL_SRCS-y       += xc_kexec.c
 CTRL_SRCS-y       += xc_resource.c
 CTRL_SRCS-$(CONFIG_X86) += xc_psr.c
 CTRL_SRCS-$(CONFIG_X86) += xc_pagetab.c
-CTRL_SRCS-$(CONFIG_Linux) += xc_linux.c xc_linux_osdep.c
-CTRL_SRCS-$(CONFIG_FreeBSD) += xc_freebsd.c xc_freebsd_osdep.c
+CTRL_SRCS-$(CONFIG_Linux) += xc_linux.c
+CTRL_SRCS-$(CONFIG_FreeBSD) += xc_freebsd.c
 CTRL_SRCS-$(CONFIG_SunOS) += xc_solaris.c
 CTRL_SRCS-$(CONFIG_NetBSD) += xc_netbsd.c
 CTRL_SRCS-$(CONFIG_NetBSDRump) += xc_netbsd.c
@@ -126,7 +126,7 @@ $(CTRL_PIC_OBJS) $(GUEST_PIC_OBJS): CFLAGS += -include $(XEN_ROOT)/tools/config.
 # libxenguest includes xc_private.h, so needs this despite not using
 # this functionality directly.
 $(CTRL_LIB_OBJS) $(GUEST_LIB_OBJS) \
-$(CTRL_PIC_OBJS) $(GUEST_PIC_OBJS): CFLAGS += $(CFLAGS_libxencall)
+$(CTRL_PIC_OBJS) $(GUEST_PIC_OBJS): CFLAGS += $(CFLAGS_libxencall) $(CFLAGS_libxenforeignmemory)
 
 $(CTRL_LIB_OBJS) $(CTRL_PIC_OBJS): CFLAGS += $(CFLAGS_libxengnttab) $(CFLAGS_libxengntshr)
 
@@ -208,7 +208,7 @@ libxenctrl.so.$(MAJOR): libxenctrl.so.$(MAJOR).$(MINOR)
 	$(SYMLINK_SHLIB) $< $@
 
 libxenctrl.so.$(MAJOR).$(MINOR): $(CTRL_PIC_OBJS)
-	$(CC) $(LDFLAGS) $(PTHREAD_LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenctrl.so.$(MAJOR) $(SHLIB_LDFLAGS) -o $@ $^ $(LDLIBS_libxentoollog) $(LDLIBS_libxenevtchn) $(LDLIBS_libxengnttab) $(LDLIBS_libxengntshr) $(LDLIBS_libxencall) $(PTHREAD_LIBS) $(APPEND_LDFLAGS)
+	$(CC) $(LDFLAGS) $(PTHREAD_LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenctrl.so.$(MAJOR) $(SHLIB_LDFLAGS) -o $@ $^ $(LDLIBS_libxentoollog) $(LDLIBS_libxenevtchn) $(LDLIBS_libxengnttab) $(LDLIBS_libxengntshr) $(LDLIBS_libxencall) $(LDLIBS_libxenforeignmemory) $(PTHREAD_LIBS) $(APPEND_LDFLAGS)
 
 # libxenguest
 
diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h
index 201fd70..bfa11a7 100644
--- a/tools/libxc/include/xenctrl.h
+++ b/tools/libxc/include/xenctrl.h
@@ -1349,32 +1349,6 @@ int xc_lockprof_query(xc_interface *xch,
 void *xc_memalign(xc_interface *xch, size_t alignment, size_t size);
 
 /**
- * Memory maps a range within one domain to a local address range.  Mappings
- * should be unmapped with munmap and should follow the same rules as mmap
- * regarding page alignment.  Returns NULL on failure.
- *
- * @parm xch a handle on an open hypervisor interface
- * @parm dom the domain to map memory from
- * @parm size the amount of memory to map (in multiples of page size)
- * @parm prot same flag as in mmap().
- * @parm mfn the frame address to map.
- */
-void *xc_map_foreign_range(xc_interface *xch, uint32_t dom,
-                            int size, int prot,
-                            unsigned long mfn );
-
-void *xc_map_foreign_pages(xc_interface *xch, uint32_t dom, int prot,
-                           const xen_pfn_t *arr, int num );
-
-/**
- * Like xc_map_foreign_pages(), except it can succeed partially.
- * When a page cannot be mapped, its respective field in @err is
- * set to the corresponding errno value.
- */
-void *xc_map_foreign_bulk(xc_interface *xch, uint32_t dom, int prot,
-                          const xen_pfn_t *arr, int *err, unsigned int num);
-
-/**
  * Translates a virtual address in the context of a given domain and
  * vcpu returning the GFN containing the address (that is, an MFN for 
  * PV guests, a PFN for HVM guests).  Returns 0 for failure.
diff --git a/tools/libxc/include/xenctrl_compat.h b/tools/libxc/include/xenctrl_compat.h
index d99fa11..54c23a4 100644
--- a/tools/libxc/include/xenctrl_compat.h
+++ b/tools/libxc/include/xenctrl_compat.h
@@ -12,6 +12,42 @@
 #ifndef XENCTRL_COMPAT_H
 #define XENCTRL_COMPAT_H
 
+#ifdef XC_WANT_COMPAT_MAP_FOREIGN_API
+/**
+ * Memory maps a range within one domain to a local address range.  Mappings
+ * should be unmapped with munmap and should follow the same rules as mmap
+ * regarding page alignment.  Returns NULL on failure.
+ *
+ * @parm xch a handle on an open hypervisor interface
+ * @parm dom the domain to map memory from
+ * @parm size the amount of memory to map (in multiples of page size)
+ * @parm prot same flag as in mmap().
+ * @parm mfn the frame address to map.
+ */
+void *xc_map_foreign_range(xc_interface *xch, uint32_t dom,
+                            int size, int prot,
+                            unsigned long mfn );
+
+void *xc_map_foreign_pages(xc_interface *xch, uint32_t dom, int prot,
+                           const xen_pfn_t *arr, int num );
+
+/* Nothing within the library itself other than the compat wrapper
+ * itself should be using this, everything inside has access to
+ * xenforeignmemory_map().
+ */
+#if !defined(XC_INTERNAL_COMPAT_MAP_FOREIGN_API) || \
+     defined(XC_BUILDING_COMPAT_MAP_FOREIGN_API)
+/**
+ * Like xc_map_foreign_pages(), except it can succeed partially.
+ * When a page cannot be mapped, its respective field in @err is
+ * set to the corresponding errno value.
+ */
+void *xc_map_foreign_bulk(xc_interface *xch, uint32_t dom, int prot,
+                          const xen_pfn_t *arr, int *err, unsigned int num);
+#endif
+
+#endif
+
 #ifdef XC_WANT_COMPAT_EVTCHN_API
 
 typedef struct xenevtchn_handle xc_evtchn;
diff --git a/tools/libxc/xc_domain_restore.c b/tools/libxc/xc_domain_restore.c
index 8435f6b..5d44512 100644
--- a/tools/libxc/xc_domain_restore.c
+++ b/tools/libxc/xc_domain_restore.c
@@ -1284,8 +1284,8 @@ static int apply_batch(xc_interface *xch, uint32_t dom, struct restore_ctx *ctx,
         PERROR("allocation for pfn_err failed");
         return -1;
     }
-    region_base = xc_map_foreign_bulk(
-        xch, dom, PROT_WRITE, region_mfn, pfn_err, j);
+    region_base = xenforeignmemory_map(xch->fmem,
+        dom, PROT_WRITE, region_mfn, pfn_err, j);
 
     if ( region_base == NULL )
     {
diff --git a/tools/libxc/xc_domain_save.c b/tools/libxc/xc_domain_save.c
index 3222473..412819f 100644
--- a/tools/libxc/xc_domain_save.c
+++ b/tools/libxc/xc_domain_save.c
@@ -1265,8 +1265,8 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
             if ( batch == 0 )
                 goto skip; /* vanishingly unlikely... */
 
-            region_base = xc_map_foreign_bulk(
-                xch, dom, PROT_READ, pfn_type, pfn_err, batch);
+            region_base = xenforeignmemory_map(xch->fmem,
+                dom, PROT_READ, pfn_type, pfn_err, batch);
             if ( region_base == NULL )
             {
                 PERROR("map batch failed");
diff --git a/tools/libxc/xc_foreign_memory.c b/tools/libxc/xc_foreign_memory.c
index c96489d..b6bf132 100644
--- a/tools/libxc/xc_foreign_memory.c
+++ b/tools/libxc/xc_foreign_memory.c
@@ -18,6 +18,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
+#define XC_BUILDING_COMPAT_MAP_FOREIGN_API
 #include "xc_private.h"
 
 void *xc_map_foreign_pages(xc_interface *xch, uint32_t dom, int prot,
@@ -35,7 +36,7 @@ void *xc_map_foreign_pages(xc_interface *xch, uint32_t dom, int prot,
     if (!err)
         return NULL;
 
-    res = xc_map_foreign_bulk(xch, dom, prot, arr, err, num);
+    res = xenforeignmemory_map(xch->fmem, dom, prot, arr, err, num);
     if (res) {
         for (i = 0; i < num; i++) {
             if (err[i]) {
@@ -101,53 +102,11 @@ void *xc_map_foreign_ranges(xc_interface *xch,
     return ret;
 }
 
-/*
- * stub for all not yet converted OSes (NetBSD and Solaris). New OSes should
- * just implement xc_map_foreign_bulk.
- */
-#if defined(__NetBSD__) || defined(__sun__)
-void *osdep_map_foreign_batch(xc_interface *xch, uint32_t dom, int prot,
-                              xen_pfn_t *arr, int num );
-void *xc_map_foreign_bulk(xc_interface *xch,
-                          uint32_t dom, int prot,
+void *xc_map_foreign_bulk(xc_interface *xch, uint32_t dom, int prot,
                           const xen_pfn_t *arr, int *err, unsigned int num)
 {
-    xen_pfn_t *pfn;
-    unsigned int i;
-    void *ret;
-
-    if ((int)num <= 0) {
-        errno = EINVAL;
-        return NULL;
-    }
-
-    pfn = malloc(num * sizeof(*pfn));
-    if (!pfn) {
-        errno = ENOMEM;
-        return NULL;
-    }
-
-    memcpy(pfn, arr, num * sizeof(*arr));
-    ret = osdep_map_foreign_batch(xch, dom, prot, pfn, num);
-
-    if (ret) {
-        for (i = 0; i < num; ++i)
-            switch (pfn[i] ^ arr[i]) {
-            case 0:
-                err[i] = 0;
-                break;
-            default:
-                err[i] = -EINVAL;
-                break;
-            }
-    } else
-        memset(err, 0, num * sizeof(*err));
-
-    free(pfn);
-
-    return ret;
+    return xenforeignmemory_map(xch->fmem, dom, prot, arr, err, num);
 }
-#endif
 
 /*
  * Local variables:
diff --git a/tools/libxc/xc_freebsd_osdep.c b/tools/libxc/xc_freebsd_osdep.c
deleted file mode 100644
index d09e0da..0000000
--- a/tools/libxc/xc_freebsd_osdep.c
+++ /dev/null
@@ -1,137 +0,0 @@
- /******************************************************************************
- *
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- *
- * xc_gnttab functions:
- * Copyright (c) 2007-2008, D G Murray <Derek.Murray@cl.cam.ac.uk>
- *
- * This library 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 of the License.
- *
- * This library 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.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#include <errno.h>
-#include <fcntl.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <sys/mman.h>
-#include <sys/ioctl.h>
-
-#include <xen/memory.h>
-
-#include "xc_private.h"
-
-#define PRIVCMD_DEV     "/dev/xen/privcmd"
-
-/*------------------------- Privcmd device interface -------------------------*/
-int osdep_privcmd_open(xc_interface *xch)
-{
-    int flags, saved_errno;
-    int fd = open(PRIVCMD_DEV, O_RDWR);
-
-    if ( fd == -1 )
-    {
-        PERROR("Could not obtain handle on privileged command interface "
-               PRIVCMD_DEV);
-        return -1
-    }
-
-    /*
-     * Although we return the file handle as the 'xc handle' the API
-     * does not specify / guarentee that this integer is in fact
-     * a file handle. Thus we must take responsiblity to ensure
-     * it doesn't propagate (ie leak) outside the process.
-     */
-    if ( (flags = fcntl(fd, F_GETFD)) < 0 )
-    {
-        PERROR("Could not get file handle flags");
-        goto error;
-    }
-
-    flags |= FD_CLOEXEC;
-
-    if ( fcntl(fd, F_SETFD, flags) < 0 )
-    {
-        PERROR("Could not set file handle flags");
-        goto error;
-    }
-
-    xch->privcmdfd = fd;
-    return 0;
-
- error:
-    saved_errno = errno;
-    close(fd);
-    errno = saved_errno;
-
-    return -1;
-}
-
-int osdep_privcmd_close(xc_interface *xch)
-{
-    int fd = xch->privcmdfd;
-    if ( fd == -1 )
-        return 0;
-    return close(fd);
-}
-
-/*----------------------- Privcmd foreign map interface ----------------------*/
-void *xc_map_foreign_bulk(xc_interface *xch,
-                          uint32_t dom, int prot,
-                          const xen_pfn_t *arr, int *err,
-                          unsigned int num)
-{
-    int fd = xch->privcmdfd;
-    privcmd_mmapbatch_t ioctlx;
-    void *addr;
-    int rc;
-
-    addr = mmap(NULL, num << XC_PAGE_SHIFT, prot, MAP_SHARED, fd, 0);
-    if ( addr == MAP_FAILED )
-    {
-        PERROR("xc_map_foreign_bulk: mmap failed");
-        return NULL;
-    }
-
-    ioctlx.num = num;
-    ioctlx.dom = dom;
-    ioctlx.addr = (unsigned long)addr;
-    ioctlx.arr = arr;
-    ioctlx.err = err;
-
-    rc = ioctl(fd, IOCTL_PRIVCMD_MMAPBATCH, &ioctlx);
-    if ( rc < 0 )
-    {
-        int saved_errno = errno;
-        PERROR("xc_map_foreign_bulk: ioctl failed");
-        (void)munmap(addr, num << XC_PAGE_SHIFT);
-        errno = saved_errno;
-        return NULL;
-    }
-
-    return addr;
-}
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/tools/libxc/xc_linux_osdep.c b/tools/libxc/xc_linux_osdep.c
deleted file mode 100644
index 9f8805a..0000000
--- a/tools/libxc/xc_linux_osdep.c
+++ /dev/null
@@ -1,296 +0,0 @@
- /******************************************************************************
- *
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- *
- * xc_gnttab functions:
- * Copyright (c) 2007-2008, D G Murray <Derek.Murray@cl.cam.ac.uk>
- *
- * This library 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 of the License.
- *
- * This library 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.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#include <errno.h>
-#include <fcntl.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <sys/mman.h>
-#include <sys/ioctl.h>
-
-#include <xen/memory.h>
-
-#include "xenctrl.h"
-
-#include "xc_private.h"
-
-#define ROUNDUP(_x,_w) (((unsigned long)(_x)+(1UL<<(_w))-1) & ~((1UL<<(_w))-1))
-
-int osdep_privcmd_open(xc_interface *xch)
-{
-    int flags, saved_errno;
-    int fd = open("/proc/xen/privcmd", O_RDWR);
-
-    if ( fd == -1 )
-    {
-        PERROR("Could not obtain handle on privileged command interface");
-        return -1;
-    }
-
-    /* Although we return the file handle as the 'xc handle' the API
-       does not specify / guarentee that this integer is in fact
-       a file handle. Thus we must take responsiblity to ensure
-       it doesn't propagate (ie leak) outside the process */
-    if ( (flags = fcntl(fd, F_GETFD)) < 0 )
-    {
-        PERROR("Could not get file handle flags");
-        goto error;
-    }
-
-    flags |= FD_CLOEXEC;
-
-    if ( fcntl(fd, F_SETFD, flags) < 0 )
-    {
-        PERROR("Could not set file handle flags");
-        goto error;
-    }
-
-    xch->privcmdfd = fd;
-    return 0;
-
- error:
-    saved_errno = errno;
-    close(fd);
-    errno = saved_errno;
-    return -1;
-}
-
-int osdep_privcmd_close(xc_interface *xch)
-{
-    int fd = xch->privcmdfd;
-    if (fd == -1)
-        return 0;
-    return close(fd);
-}
-
-static int map_foreign_batch_single(int fd, uint32_t dom,
-                                    xen_pfn_t *mfn, unsigned long addr)
-{
-    privcmd_mmapbatch_t ioctlx;
-    int rc;
-
-    ioctlx.num = 1;
-    ioctlx.dom = dom;
-    ioctlx.addr = addr;
-    ioctlx.arr = mfn;
-
-    do
-    {
-        *mfn ^= PRIVCMD_MMAPBATCH_PAGED_ERROR;
-        usleep(100);
-        rc = ioctl(fd, IOCTL_PRIVCMD_MMAPBATCH, &ioctlx);
-    }
-    while ( (rc < 0) && (errno == ENOENT) );
-
-    return rc;
-}
-
-/*
- * Retry mmap of all paged gfns in batches
- * retuns < 0 on fatal error
- * returns 0 if all gfns left paging state
- * returns > 0 if some gfns are still in paging state
- *
- * Walk all gfns and try to assemble blocks of gfns in paging state.
- * This will keep the request ring full and avoids delays.
- */
-static int retry_paged(int fd, uint32_t dom, void *addr,
-                       const xen_pfn_t *arr, int *err, unsigned int num)
-{
-    privcmd_mmapbatch_v2_t ioctlx;
-    int rc, paged = 0, i = 0;
-    
-    do
-    {
-        /* Skip gfns not in paging state */
-        if ( err[i] != -ENOENT )
-        {
-            i++;
-            continue;
-        }
-
-        paged++;
-
-        /* At least one gfn is still in paging state */
-        ioctlx.num = 1;
-        ioctlx.dom = dom;
-        ioctlx.addr = (unsigned long)addr + ((unsigned long)i<<XC_PAGE_SHIFT);
-        ioctlx.arr = arr + i;
-        ioctlx.err = err + i;
-        
-        /* Assemble a batch of requests */
-        while ( ++i < num )
-        {
-            if ( err[i] != -ENOENT )
-                break;
-            ioctlx.num++;
-        }
-        
-        /* Send request and abort on fatal error */
-        rc = ioctl(fd, IOCTL_PRIVCMD_MMAPBATCH_V2, &ioctlx);
-        if ( rc < 0 && errno != ENOENT )
-            goto out;
-
-    } while ( i < num );
-    
-    rc = paged;
-out:
-    return rc;
-}
-
-void *xc_map_foreign_bulk(xc_interface *xch,
-                          uint32_t dom, int prot,
-                          const xen_pfn_t *arr, int *err, unsigned int num)
-{
-    int fd = xch->privcmdfd;
-    privcmd_mmapbatch_v2_t ioctlx;
-    void *addr;
-    unsigned int i;
-    int rc;
-
-    addr = mmap(NULL, (unsigned long)num << XC_PAGE_SHIFT, prot, MAP_SHARED,
-                fd, 0);
-    if ( addr == MAP_FAILED )
-    {
-        PERROR("xc_map_foreign_bulk: mmap failed");
-        return NULL;
-    }
-
-    ioctlx.num = num;
-    ioctlx.dom = dom;
-    ioctlx.addr = (unsigned long)addr;
-    ioctlx.arr = arr;
-    ioctlx.err = err;
-
-    rc = ioctl(fd, IOCTL_PRIVCMD_MMAPBATCH_V2, &ioctlx);
-
-    /* Command was recognized, some gfn in arr are in paging state */
-    if ( rc < 0 && errno == ENOENT )
-    {
-        do {
-            usleep(100);
-            rc = retry_paged(fd, dom, addr, arr, err, num);
-        } while ( rc > 0 );
-    }
-    /* Command was not recognized, use fall back */
-    else if ( rc < 0 && errno == EINVAL && (int)num > 0 )
-    {
-        /*
-         * IOCTL_PRIVCMD_MMAPBATCH_V2 is not supported - fall back to
-         * IOCTL_PRIVCMD_MMAPBATCH.
-         */
-        privcmd_mmapbatch_t ioctlx;
-        xen_pfn_t *pfn;
-        unsigned int pfn_arr_size = ROUNDUP((num * sizeof(*pfn)), XC_PAGE_SHIFT);
-
-        if ( pfn_arr_size <= XC_PAGE_SIZE )
-            pfn = alloca(num * sizeof(*pfn));
-        else
-        {
-            pfn = mmap(NULL, pfn_arr_size, PROT_READ | PROT_WRITE,
-                       MAP_PRIVATE | MAP_ANON | MAP_POPULATE, -1, 0);
-            if ( pfn == MAP_FAILED )
-            {
-                PERROR("xc_map_foreign_bulk: mmap of pfn array failed");
-                (void)munmap(addr, (unsigned long)num << XC_PAGE_SHIFT);
-                return NULL;
-            }
-        }
-
-        memcpy(pfn, arr, num * sizeof(*arr));
-
-        ioctlx.num = num;
-        ioctlx.dom = dom;
-        ioctlx.addr = (unsigned long)addr;
-        ioctlx.arr = pfn;
-
-        rc = ioctl(fd, IOCTL_PRIVCMD_MMAPBATCH, &ioctlx);
-
-        rc = rc < 0 ? -errno : 0;
-
-        for ( i = 0; i < num; ++i )
-        {
-            switch ( pfn[i] ^ arr[i] )
-            {
-            case 0:
-                err[i] = rc != -ENOENT ? rc : 0;
-                continue;
-            default:
-                err[i] = -EINVAL;
-                continue;
-            case PRIVCMD_MMAPBATCH_PAGED_ERROR:
-                if ( rc != -ENOENT )
-                {
-                    err[i] = rc ?: -EINVAL;
-                    continue;
-                }
-                rc = map_foreign_batch_single(fd, dom, pfn + i,
-                        (unsigned long)addr + ((unsigned long)i<<XC_PAGE_SHIFT));
-                if ( rc < 0 )
-                {
-                    rc = -errno;
-                    break;
-                }
-                rc = -ENOENT;
-                continue;
-            }
-            break;
-        }
-
-        if ( pfn_arr_size > XC_PAGE_SIZE )
-            munmap(pfn, pfn_arr_size);
-
-        if ( rc == -ENOENT && i == num )
-            rc = 0;
-        else if ( rc )
-        {
-            errno = -rc;
-            rc = -1;
-        }
-    }
-
-    if ( rc < 0 )
-    {
-        int saved_errno = errno;
-
-        PERROR("xc_map_foreign_bulk: ioctl failed");
-        (void)munmap(addr, (unsigned long)num << XC_PAGE_SHIFT);
-        errno = saved_errno;
-        return NULL;
-    }
-
-    return addr;
-}
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/tools/libxc/xc_minios.c b/tools/libxc/xc_minios.c
index 1616c58..7373e54 100644
--- a/tools/libxc/xc_minios.c
+++ b/tools/libxc/xc_minios.c
@@ -40,40 +40,11 @@ void minios_interface_close_fd(int fd);
 
 extern void minios_interface_close_fd(int fd);
 
-int osdep_privcmd_open(xc_interface *xch)
-{
-    int fd = alloc_fd(FTYPE_XC);
-
-    if ( fd == -1)
-        return -1;
-
-    xch->privcmdfd = fd;
-    return 0;
-}
-
-int osdep_privcmd_close(xc_interface *xch)
-{
-    int fd = xch->privcmdfd;
-    return close(fd);
-}
-
 void minios_interface_close_fd(int fd)
 {
     files[fd].type = FTYPE_NONE;
 }
 
-void *xc_map_foreign_bulk(xc_interface *xch,
-                          uint32_t dom, int prot,
-                          const xen_pfn_t *arr, int *err, unsigned int num)
-{
-    unsigned long pt_prot = 0;
-    if (prot & PROT_READ)
-	pt_prot = L1_PROT_RO;
-    if (prot & PROT_WRITE)
-	pt_prot = L1_PROT;
-    return map_frames_ex(arr, num, 1, 0, 1, dom, err, pt_prot);
-}
-
 /* Optionally flush file to disk and discard page cache */
 void discard_file_cache(xc_interface *xch, int fd, int flush)
 {
diff --git a/tools/libxc/xc_netbsd.c b/tools/libxc/xc_netbsd.c
index 2654d18..8d6742d 100644
--- a/tools/libxc/xc_netbsd.c
+++ b/tools/libxc/xc_netbsd.c
@@ -23,79 +23,6 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <malloc.h>
-#include <sys/mman.h>
-
-int osdep_privcmd_open(xc_interface *xch)
-{
-    int flags, saved_errno;
-    int fd = open("/kern/xen/privcmd", O_RDWR);
-
-    if ( fd == -1 )
-    {
-        PERROR("Could not obtain handle on privileged command interface");
-        return -1;
-    }
-
-    /* Although we return the file handle as the 'xc handle' the API
-       does not specify / guarentee that this integer is in fact
-       a file handle. Thus we must take responsiblity to ensure
-       it doesn't propagate (ie leak) outside the process */
-    if ( (flags = fcntl(fd, F_GETFD)) < 0 )
-    {
-        PERROR("Could not get file handle flags");
-        goto error;
-    }
-    flags |= FD_CLOEXEC;
-    if ( fcntl(fd, F_SETFD, flags) < 0 )
-    {
-        PERROR("Could not set file handle flags");
-        goto error;
-    }
-
-    xch->privcmdfd = fd;
-    return 0;
-
- error:
-    saved_errno = errno;
-    close(fd);
-    errno = saved_errno;
-    return -1;
-}
-
-int osdep_privcmd_close(xc_interface *xch)
-{
-    int fd = xch->privcmdfd;
-    return close(fd);
-}
-
-void *osdep_map_foreign_batch(xc_interface *xch,
-                              uint32_t dom, int prot,
-                              xen_pfn_t *arr, int num)
-{
-    int fd = xch->privcmdfd;
-    privcmd_mmapbatch_t ioctlx;
-    void *addr;
-    addr = mmap(NULL, num*XC_PAGE_SIZE, prot, MAP_ANON | MAP_SHARED, -1, 0);
-    if ( addr == MAP_FAILED ) {
-        PERROR("osdep_map_foreign_batch: mmap failed");
-        return NULL;
-    }
-
-    ioctlx.num=num;
-    ioctlx.dom=dom;
-    ioctlx.addr=(unsigned long)addr;
-    ioctlx.arr=arr;
-    if ( ioctl(fd, IOCTL_PRIVCMD_MMAPBATCH, &ioctlx) < 0 )
-    {
-        int saved_errno = errno;
-        PERROR("osdep_map_foreign_batch: ioctl failed");
-        (void)munmap(addr, num*XC_PAGE_SIZE);
-        errno = saved_errno;
-        return NULL;
-    }
-    return addr;
-
-}
 
 /* Optionally flush file to disk and discard page cache */
 void discard_file_cache(xc_interface *xch, int fd, int flush) 
diff --git a/tools/libxc/xc_private.c b/tools/libxc/xc_private.c
index 00f96ba..94ec444 100644
--- a/tools/libxc/xc_private.c
+++ b/tools/libxc/xc_private.c
@@ -59,11 +59,12 @@ struct xc_interface_core *xc_interface_open(xentoollog_logger *logger,
     if (open_flags & XC_OPENFLAG_DUMMY)
         return xch; /* We are done */
 
-    if ( osdep_privcmd_open(xch) < 0 )
-        goto err;
-
     xch->xcall = xencall_open(xch->error_handler,
         open_flags & XC_OPENFLAG_NON_REENTRANT ? XENCALL_OPENFLAG_NON_REENTRANT : 0U);
+    if ( xch->xcall == NULL )
+        goto err;
+
+    xch->fmem = xenforeignmemory_open(xch->error_handler, 0);
 
     if ( xch->xcall == NULL )
         goto err;
@@ -71,7 +72,7 @@ struct xc_interface_core *xc_interface_open(xentoollog_logger *logger,
     return xch;
 
  err:
-    osdep_privcmd_close(xch);
+    xencall_close(xch->xcall);
     xtl_logger_destroy(xch->error_handler_tofree);
     if (xch != &xch_buf) free(xch);
     return NULL;
@@ -87,8 +88,8 @@ int xc_interface_close(xc_interface *xch)
     rc = xencall_close(xch->xcall);
     if (rc) PERROR("Could not close xencall interface");
 
-    rc = osdep_privcmd_close(xch);
-    if (rc) PERROR("Could not close hypervisor interface");
+    rc = xenforeignmemory_close(xch->fmem);
+    if (rc) PERROR("Could not close foreign memory interface");
 
     xtl_logger_destroy(xch->dombuild_logger_tofree);
     xtl_logger_destroy(xch->error_handler_tofree);
diff --git a/tools/libxc/xc_private.h b/tools/libxc/xc_private.h
index c8c2bdc..b230854 100644
--- a/tools/libxc/xc_private.h
+++ b/tools/libxc/xc_private.h
@@ -30,8 +30,13 @@
 #include <sys/ioctl.h>
 
 #include "_paths.h"
+
+#define XC_WANT_COMPAT_MAP_FOREIGN_API
+#define XC_INTERNAL_COMPAT_MAP_FOREIGN_API
 #include "xenctrl.h"
+
 #include <xencall.h>
+#include <xenforeignmemory.h>
 
 #include <xen/sys/privcmd.h>
 
@@ -95,11 +100,11 @@ struct xc_interface_core {
     FILE *dombuild_logger_file;
     const char *currently_progress_reporting;
 
-    /* Privcmd interface */
-    int privcmdfd;
-
     /* Hypercall interface */
     xencall_handle *xcall;
+
+    /* Foreign mappings */
+    xenforeignmemory_handle *fmem;
 };
 
 int osdep_privcmd_open(xc_interface *xch);
diff --git a/tools/libxc/xc_solaris.c b/tools/libxc/xc_solaris.c
index e1e126d..c2e87d1 100644
--- a/tools/libxc/xc_solaris.c
+++ b/tools/libxc/xc_solaris.c
@@ -20,81 +20,8 @@
 
 #include "xc_private.h"
 
-#include <xen/memory.h>
-#include <unistd.h>
-#include <fcntl.h>
 #include <malloc.h>
 
-int osdep_privcmd_open(xc_interface *xch)
-{
-    int flags, saved_errno;
-    int fd = open("/dev/xen/privcmd", O_RDWR);
-
-    if ( fd == -1 )
-    {
-        PERROR("Could not obtain handle on privileged command interface");
-        return -1;
-    }
-
-    /* Although we return the file handle as the 'xc handle' the API
-       does not specify / guarentee that this integer is in fact
-       a file handle. Thus we must take responsiblity to ensure
-       it doesn't propagate (ie leak) outside the process */
-    if ( (flags = fcntl(fd, F_GETFD)) < 0 )
-    {
-        PERROR("Could not get file handle flags");
-        goto error;
-    }
-    flags |= FD_CLOEXEC;
-    if ( fcntl(fd, F_SETFD, flags) < 0 )
-    {
-        PERROR("Could not set file handle flags");
-        goto error;
-    }
-
-    xch->privcmdfd = fd;
-    return 0;
-
- error:
-    saved_errno = errno;
-    close(fd);
-    errno = saved_errno;
-    return -1;
-}
-
-int osdep_privcmd_close(xc_interface *xch)
-{
-    int fd = xch->privcmdfd;
-    return close(fd);
-}
-
-void *osdep_map_foreign_batch(xc_interface *xch,
-                              uint32_t dom, int prot,
-                              xen_pfn_t *arr, int num)
-{
-    int fd = xch->privcmdfd;
-    privcmd_mmapbatch_t ioctlx;
-    void *addr;
-    addr = mmap(NULL, num*XC_PAGE_SIZE, prot, MAP_SHARED, fd, 0);
-    if ( addr == MAP_FAILED )
-        return NULL;
-
-    ioctlx.num=num;
-    ioctlx.dom=dom;
-    ioctlx.addr=(unsigned long)addr;
-    ioctlx.arr=arr;
-    if ( ioctl(fd, IOCTL_PRIVCMD_MMAPBATCH, &ioctlx) < 0 )
-    {
-        int saved_errno = errno;
-        PERROR("XXXXXXXX");
-        (void)munmap(addr, num*XC_PAGE_SIZE);
-        errno = saved_errno;
-        return NULL;
-    }
-    return addr;
-
-}
-
 /* Optionally flush file to disk and discard page cache */
 void discard_file_cache(xc_interface *xch, int fd, int flush) 
 {
diff --git a/tools/libxc/xc_sr_restore.c b/tools/libxc/xc_sr_restore.c
index bf1ee15..4bbda9d 100644
--- a/tools/libxc/xc_sr_restore.c
+++ b/tools/libxc/xc_sr_restore.c
@@ -315,8 +315,8 @@ static int process_page_data(struct xc_sr_context *ctx, unsigned count,
     if ( nr_pages == 0 )
         goto done;
 
-    mapping = guest_page = xc_map_foreign_bulk(
-        xch, ctx->domid, PROT_READ | PROT_WRITE,
+    mapping = guest_page = xenforeignmemory_map(xch->fmem,
+        ctx->domid, PROT_READ | PROT_WRITE,
         mfns, map_errs, nr_pages);
     if ( !mapping )
     {
diff --git a/tools/libxc/xc_sr_save.c b/tools/libxc/xc_sr_save.c
index d63b783..2672ad3 100644
--- a/tools/libxc/xc_sr_save.c
+++ b/tools/libxc/xc_sr_save.c
@@ -153,8 +153,8 @@ static int write_batch(struct xc_sr_context *ctx)
 
     if ( nr_pages > 0 )
     {
-        guest_mapping = xc_map_foreign_bulk(
-            xch, ctx->domid, PROT_READ, mfns, errors, nr_pages);
+        guest_mapping = xenforeignmemory_map(xch->fmem,
+            ctx->domid, PROT_READ, mfns, errors, nr_pages);
         if ( !guest_mapping )
         {
             PERROR("Failed to map guest pages");
diff --git a/tools/libxc/xc_vm_event.c b/tools/libxc/xc_vm_event.c
index 4d7e7cc..940efd7 100644
--- a/tools/libxc/xc_vm_event.c
+++ b/tools/libxc/xc_vm_event.c
@@ -74,8 +74,9 @@ void *xc_vm_event_enable(xc_interface *xch, domid_t domain_id, int param,
 
     ring_pfn = pfn;
     mmap_pfn = pfn;
-    ring_page = xc_map_foreign_bulk(xch, domain_id, PROT_READ | PROT_WRITE,
-				    &mmap_pfn, &err, 1);
+    ring_page = xenforeignmemory_map(xch->fmem,
+				     domain_id, PROT_READ | PROT_WRITE,
+				     &mmap_pfn, &err, 1);
     if ( !ring_page )
     {
         /* Map failed, populate ring page */
@@ -88,8 +89,9 @@ void *xc_vm_event_enable(xc_interface *xch, domid_t domain_id, int param,
         }
 
         mmap_pfn = ring_pfn;
-        ring_page = xc_map_foreign_bulk(xch, domain_id, PROT_READ | PROT_WRITE,
-					&mmap_pfn, &err, 1);
+        ring_page = xenforeignmemory_map(xch->fmem,
+					 domain_id, PROT_READ | PROT_WRITE,
+					 &mmap_pfn, &err, 1);
         if ( !ring_page )
         {
             PERROR("Could not map the ring page: %d\n", err);
diff --git a/tools/libxc/xg_private.h b/tools/libxc/xg_private.h
index 1910361..0baf403 100644
--- a/tools/libxc/xg_private.h
+++ b/tools/libxc/xg_private.h
@@ -27,9 +27,8 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 
-#include "xenctrl.h"
-#include "xenguest.h"
 #include "xc_private.h"
+#include "xenguest.h"
 
 #include <xen/memory.h>
 #include <xen/elfnote.h>
diff --git a/tools/libxenforeignmemory/Makefile b/tools/libxenforeignmemory/Makefile
new file mode 100644
index 0000000..4c84115
--- /dev/null
+++ b/tools/libxenforeignmemory/Makefile
@@ -0,0 +1,67 @@
+XEN_ROOT = $(CURDIR)/../..
+include $(XEN_ROOT)/tools/Rules.mk
+
+MAJOR    = 1
+MINOR    = 0
+SHLIB_LDFLAGS += -Wl,--version-script=libxenforeignmemory.map
+
+CFLAGS   += -Werror -Wmissing-prototypes
+CFLAGS   += -I./include $(CFLAGS_xeninclude)
+CFLAGS   += $(CFLAGS_libxentoollog)
+
+SRCS-y                 += core.c
+SRCS-$(CONFIG_Linux)   += linux.c
+SRCS-$(CONFIG_FreeBSD) += freebsd.c
+SRCS-$(CONFIG_SunOS)   += compat.c solaris.c
+SRCS-$(CONFIG_NetBSD)  += compat.c netbsd.c
+SRCS-$(CONFIG_MiniOS)  += minios.c
+
+LIB_OBJS := $(patsubst %.c,%.o,$(SRCS-y))
+PIC_OBJS := $(patsubst %.c,%.opic,$(SRCS-y))
+
+LIB := libxenforeignmemory.a
+ifneq ($(nosharedlibs),y)
+LIB += libxenforeignmemory.so
+endif
+
+.PHONY: all
+all: build
+
+.PHONY: build
+build:
+	$(MAKE) libs
+
+.PHONY: libs
+libs: headers.chk $(LIB)
+
+headers.chk: $(wildcard include/*.h)
+
+libxenforeignmemory.a: $(LIB_OBJS)
+	$(AR) rc $@ $^
+
+libxenforeignmemory.so: libxenforeignmemory.so.$(MAJOR)
+	$(SYMLINK_SHLIB) $< $@
+libxenforeignmemory.so.$(MAJOR): libxenforeignmemory.so.$(MAJOR).$(MINOR)
+	$(SYMLINK_SHLIB) $< $@
+
+libxenforeignmemory.so.$(MAJOR).$(MINOR): $(PIC_OBJS) libxenforeignmemory.map
+	$(CC) $(LDFLAGS) $(PTHREAD_LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenforeignmemory.so.$(MAJOR) $(SHLIB_LDFLAGS) -o $@ $(PIC_OBJS) $(LDLIBS_libxentoollog) $(APPEND_LDFLAGS)
+
+.PHONY: install
+install: build
+	$(INSTALL_DIR) $(DESTDIR)$(libdir)
+	$(INSTALL_DIR) $(DESTDIR)$(includedir)
+	$(INSTALL_SHLIB) libxenforeignmemory.so.$(MAJOR).$(MINOR) $(DESTDIR)$(libdir)
+	$(INSTALL_DATA) libxenforeignmemory.a $(DESTDIR)$(libdir)
+	$(SYMLINK_SHLIB) libxenforeignmemory.so.$(MAJOR).$(MINOR) $(DESTDIR)$(libdir)/libxenforeignmemory.so.$(MAJOR)
+	$(SYMLINK_SHLIB) libxenforeignmemory.so.$(MAJOR) $(DESTDIR)$(libdir)/libxenforeignmemory.so
+	$(INSTALL_DATA) include/xenforeignmemory.h $(DESTDIR)$(includedir)
+
+.PHONY: TAGS
+TAGS:
+	etags -t *.c *.h
+
+.PHONY: clean
+clean:
+	rm -rf *.rpm $(LIB) *~ $(DEPS) $(LIB_OBJS) $(PIC_OBJS)
+	rm -f headers.chk
diff --git a/tools/libxenforeignmemory/compat.c b/tools/libxenforeignmemory/compat.c
new file mode 100644
index 0000000..0d2cf36
--- /dev/null
+++ b/tools/libxenforeignmemory/compat.c
@@ -0,0 +1,72 @@
+/******************************************************************************
+ *
+ * Compatibility functions for mapping foreign domain's memory.
+ *
+ * This library 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 of the License.
+ *
+ * This library 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.
+ *
+ * Split out from xc_foreign_memory.c
+ */
+#if !defined(__NetBSD__) && !defined(__sun__)
+#error Please implement xc_map_foreign_bulk directly for new ports.
+#endif
+
+#include "private.h"
+
+void *xc_map_foreign_bulk(xenforeignmem_handle *fmem,
+                          uint32_t dom, int prot,
+                          const xen_pfn_t *arr, int *err, unsigned int num)
+{
+    xen_pfn_t *pfn;
+    unsigned int i;
+    void *ret;
+
+    if ((int)num <= 0) {
+        errno = EINVAL;
+        return NULL;
+    }
+
+    pfn = malloc(num * sizeof(*pfn));
+    if (!pfn) {
+        errno = ENOMEM;
+        return NULL;
+    }
+
+    memcpy(pfn, arr, num * sizeof(*arr));
+    ret = osdep_map_foreign_batch(fmem, dom, prot, pfn, num);
+
+    if (ret) {
+        for (i = 0; i < num; ++i)
+            switch (pfn[i] ^ arr[i]) {
+            case 0:
+                err[i] = 0;
+                break;
+            default:
+                err[i] = -EINVAL;
+                break;
+            }
+    } else
+        memset(err, 0, num * sizeof(*err));
+
+    free(pfn);
+
+    return ret;
+}
+#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxenforeignmemory/core.c b/tools/libxenforeignmemory/core.c
new file mode 100644
index 0000000..efb3e54
--- /dev/null
+++ b/tools/libxenforeignmemory/core.c
@@ -0,0 +1,65 @@
+/*
+ * This library 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 of the License.
+ *
+ * This library 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 <stdlib.h>
+
+#include "private.h"
+
+xenforeignmemory_handle *xenforeignmemory_open(xentoollog_logger *logger,
+                                               unsigned open_flags)
+{
+    xenforeignmemory_handle *fmem = malloc(sizeof(*fmem));
+    int rc;
+
+    if (!fmem) return NULL;
+
+    fmem->logger = logger;
+    fmem->logger_tofree = NULL;
+
+    if (!fmem->logger) {
+        fmem->logger = fmem->logger_tofree =
+            (xentoollog_logger*)
+            xtl_createlogger_stdiostream(stderr, XTL_PROGRESS, 0);
+        if (!fmem->logger) goto err;
+    }
+
+    rc = osdep_xenforeignmemory_open(fmem);
+    if ( rc  < 0 ) goto err;
+
+    return fmem;
+
+err:
+    osdep_xenforeignmemory_close(fmem);
+    xtl_logger_destroy(fmem->logger_tofree);
+    free(fmem);
+    return NULL;
+}
+
+int xenforeignmemory_close(xenforeignmemory_handle *fmem)
+{
+    int rc;
+
+    rc = osdep_xenforeignmemory_close(fmem);
+    xtl_logger_destroy(fmem->logger_tofree);
+    free(fmem);
+    return rc;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxenforeignmemory/freebsd.c b/tools/libxenforeignmemory/freebsd.c
new file mode 100644
index 0000000..b93db51
--- /dev/null
+++ b/tools/libxenforeignmemory/freebsd.c
@@ -0,0 +1,126 @@
+ /******************************************************************************
+ *
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * This library 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 of the License.
+ *
+ * This library 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 <errno.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+
+#include "private.h"
+
+#define PRIVCMD_DEV     "/dev/xen/privcmd"
+
+int osdep_xenforeignmemory_open(xenforeignmemory_handle *fmem)
+{
+    int flags, saved_errno;
+    int fd = open(PRIVCMD_DEV, O_RDWR);
+
+    if ( fd == -1 )
+    {
+        PERROR("Could not obtain handle on privileged command interface "
+               PRIVCMD_DEV);
+        return -1;
+    }
+
+    /*
+     * Although we return the file handle as the 'xc handle' the API
+     * does not specify / guarentee that this integer is in fact
+     * a file handle. Thus we must take responsiblity to ensure
+     * it doesn't propagate (ie leak) outside the process.
+     */
+    if ( (flags = fcntl(fd, F_GETFD)) < 0 )
+    {
+        PERROR("Could not get file handle flags");
+        goto error;
+    }
+
+    flags |= FD_CLOEXEC;
+
+    if ( fcntl(fd, F_SETFD, flags) < 0 )
+    {
+        PERROR("Could not set file handle flags");
+        goto error;
+    }
+
+    fmem->fd = fd;
+    return 0;
+
+ error:
+    saved_errno = errno;
+    close(fd);
+    errno = saved_errno;
+
+    return -1;
+}
+
+int osdep_xenforeignmemory_close(xenforeignmemory_handle *fmem)
+{
+    int fd = fmem->fd;
+    if ( fd == -1 )
+        return 0;
+    return close(fd);
+}
+
+void *xenforeignmemory_map(xenforeignmemory_handle *fmem,
+                           uint32_t dom, int prot,
+                           const xen_pfn_t *arr, int *err,
+                           unsigned int num)
+{
+    int fd = fmem->fd;
+    privcmd_mmapbatch_t ioctlx;
+    void *addr;
+    int rc;
+
+    addr = mmap(NULL, num << PAGE_SHIFT, prot, MAP_SHARED, fd, 0);
+    if ( addr == MAP_FAILED )
+    {
+        PERROR("xc_map_foreign_bulk: mmap failed");
+        return NULL;
+    }
+
+    ioctlx.num = num;
+    ioctlx.dom = dom;
+    ioctlx.addr = (unsigned long)addr;
+    ioctlx.arr = arr;
+    ioctlx.err = err;
+
+    rc = ioctl(fd, IOCTL_PRIVCMD_MMAPBATCH, &ioctlx);
+    if ( rc < 0 )
+    {
+        int saved_errno = errno;
+        PERROR("xc_map_foreign_bulk: ioctl failed");
+        (void)munmap(addr, num << PAGE_SHIFT);
+        errno = saved_errno;
+        return NULL;
+    }
+
+    return addr;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxenforeignmemory/include/xenforeignmemory.h b/tools/libxenforeignmemory/include/xenforeignmemory.h
new file mode 100644
index 0000000..3f3d1c7
--- /dev/null
+++ b/tools/libxenforeignmemory/include/xenforeignmemory.h
@@ -0,0 +1,68 @@
+/*
+ * This library 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 of the License.
+ *
+ * This library 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.
+ */
+#ifndef XENFOREIGNMEMORY_H
+#define XENFOREIGNMEMORY_H
+
+/*
+ * This library allows you to map foreign domain memory, subject to
+ * permissions for both the process and the domain in which the
+ * process runs.
+ */
+
+#include <stdint.h>
+#include <stddef.h>
+
+#include <xen/xen.h>
+
+/* Callers who don't care don't need to #include <xentoollog.h> */
+typedef struct xentoollog_logger xentoollog_logger;
+
+typedef struct xenforeignmemory_handle xenforeignmemory_handle;
+
+/*
+ * Return a handle onto the hypercall driver.  Logs errors.
+ */
+xenforeignmemory_handle *xenforeignmemory_open(xentoollog_logger *logger,
+                                               unsigned open_flags);
+
+/*
+ * Close a handle previously allocated with xenforeignmemory_open().
+ */
+int xenforeignmemory_close(xenforeignmemory_handle *xmem);
+
+/*
+ * Maps a range within one domain to a local address range.  Mappings
+ * should be unmapped with munmap and should follow the same rules as mmap
+ * regarding page alignment.
+ *
+ * prot is as for mmap(2).
+ *
+ * Can partially succeed. When a page cannot be mapped, its respective
+ * field in @err is set to the corresponding errno value.
+ *
+ * Returns NULL if no pages can be mapped.
+ */
+void *xenforeignmemory_map(xenforeignmemory_handle *fmem, uint32_t dom,
+                           int prot, const xen_pfn_t *arr, int *err,
+                           unsigned int num);
+
+#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxenforeignmemory/libxenforeignmemory.map b/tools/libxenforeignmemory/libxenforeignmemory.map
new file mode 100644
index 0000000..11f0d2b
--- /dev/null
+++ b/tools/libxenforeignmemory/libxenforeignmemory.map
@@ -0,0 +1,7 @@
+VERS_1.0 {
+	global:
+		xenforeignmemory_open;
+		xenforeignmemory_close;
+		xenforeignmemory_map;
+	local: *; /* Do not expose anything by default */
+};
diff --git a/tools/libxenforeignmemory/linux.c b/tools/libxenforeignmemory/linux.c
new file mode 100644
index 0000000..6343ebe
--- /dev/null
+++ b/tools/libxenforeignmemory/linux.c
@@ -0,0 +1,284 @@
+/*
+ * This library 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 of the License.
+ *
+ * This library 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.
+ *
+ * Split out from xc_linus_osdep.c:
+ *
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ */
+
+#include <alloca.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+
+#include "private.h"
+
+#define ROUNDUP(_x,_w) (((unsigned long)(_x)+(1UL<<(_w))-1) & ~((1UL<<(_w))-1))
+
+int osdep_xenforeignmemory_open(xenforeignmemory_handle *fmem)
+{
+    int flags, saved_errno;
+    int fd = open("/proc/xen/privcmd", O_RDWR);
+
+    if ( fd == -1 )
+    {
+        PERROR("Could not obtain handle on privileged command interface");
+        return -1;
+    }
+
+    /* Although we return the file handle as the 'xc handle' the API
+       does not specify / guarentee that this integer is in fact
+       a file handle. Thus we must take responsiblity to ensure
+       it doesn't propagate (ie leak) outside the process */
+    if ( (flags = fcntl(fd, F_GETFD)) < 0 )
+    {
+        PERROR("Could not get file handle flags");
+        goto error;
+    }
+
+    flags |= FD_CLOEXEC;
+
+    if ( fcntl(fd, F_SETFD, flags) < 0 )
+    {
+        PERROR("Could not set file handle flags");
+        goto error;
+    }
+
+    fmem->fd = fd;
+    return 0;
+
+ error:
+    saved_errno = errno;
+    close(fd);
+    errno = saved_errno;
+    return -1;
+}
+
+int osdep_xenforeignmemory_close(xenforeignmemory_handle *fmem)
+{
+    int fd = fmem->fd;
+    if (fd == -1)
+        return 0;
+    return close(fd);
+}
+
+static int map_foreign_batch_single(int fd, uint32_t dom,
+                                    xen_pfn_t *mfn, unsigned long addr)
+{
+    privcmd_mmapbatch_t ioctlx;
+    int rc;
+
+    ioctlx.num = 1;
+    ioctlx.dom = dom;
+    ioctlx.addr = addr;
+    ioctlx.arr = mfn;
+
+    do
+    {
+        *mfn ^= PRIVCMD_MMAPBATCH_PAGED_ERROR;
+        usleep(100);
+        rc = ioctl(fd, IOCTL_PRIVCMD_MMAPBATCH, &ioctlx);
+    }
+    while ( (rc < 0) && (errno == ENOENT) );
+
+    return rc;
+}
+
+/*
+ * Retry mmap of all paged gfns in batches
+ * retuns < 0 on fatal error
+ * returns 0 if all gfns left paging state
+ * returns > 0 if some gfns are still in paging state
+ *
+ * Walk all gfns and try to assemble blocks of gfns in paging state.
+ * This will keep the request ring full and avoids delays.
+ */
+static int retry_paged(int fd, uint32_t dom, void *addr,
+                       const xen_pfn_t *arr, int *err, unsigned int num)
+{
+    privcmd_mmapbatch_v2_t ioctlx;
+    int rc, paged = 0, i = 0;
+
+    do
+    {
+        /* Skip gfns not in paging state */
+        if ( err[i] != -ENOENT )
+        {
+            i++;
+            continue;
+        }
+
+        paged++;
+
+        /* At least one gfn is still in paging state */
+        ioctlx.num = 1;
+        ioctlx.dom = dom;
+        ioctlx.addr = (unsigned long)addr + ((unsigned long)i<<PAGE_SHIFT);
+        ioctlx.arr = arr + i;
+        ioctlx.err = err + i;
+
+        /* Assemble a batch of requests */
+        while ( ++i < num )
+        {
+            if ( err[i] != -ENOENT )
+                break;
+            ioctlx.num++;
+        }
+
+        /* Send request and abort on fatal error */
+        rc = ioctl(fd, IOCTL_PRIVCMD_MMAPBATCH_V2, &ioctlx);
+        if ( rc < 0 && errno != ENOENT )
+            goto out;
+
+    } while ( i < num );
+
+    rc = paged;
+out:
+    return rc;
+}
+
+void *xenforeignmemory_map(xenforeignmemory_handle *fmem,
+			   uint32_t dom, int prot,
+			   const xen_pfn_t *arr, int *err, unsigned int num)
+{
+    int fd = fmem->fd;
+    privcmd_mmapbatch_v2_t ioctlx;
+    void *addr;
+    unsigned int i;
+    int rc;
+
+    addr = mmap(NULL, (unsigned long)num << PAGE_SHIFT, prot, MAP_SHARED,
+                fd, 0);
+    if ( addr == MAP_FAILED )
+    {
+        PERROR("mmap failed");
+        return NULL;
+    }
+
+    ioctlx.num = num;
+    ioctlx.dom = dom;
+    ioctlx.addr = (unsigned long)addr;
+    ioctlx.arr = arr;
+    ioctlx.err = err;
+
+    rc = ioctl(fd, IOCTL_PRIVCMD_MMAPBATCH_V2, &ioctlx);
+
+    /* Command was recognized, some gfn in arr are in paging state */
+    if ( rc < 0 && errno == ENOENT )
+    {
+        do {
+            usleep(100);
+            rc = retry_paged(fd, dom, addr, arr, err, num);
+        } while ( rc > 0 );
+    }
+    /* Command was not recognized, use fall back */
+    else if ( rc < 0 && errno == EINVAL && (int)num > 0 )
+    {
+        /*
+         * IOCTL_PRIVCMD_MMAPBATCH_V2 is not supported - fall back to
+         * IOCTL_PRIVCMD_MMAPBATCH.
+         */
+        privcmd_mmapbatch_t ioctlx;
+        xen_pfn_t *pfn;
+        unsigned int pfn_arr_size = ROUNDUP((num * sizeof(*pfn)), PAGE_SHIFT);
+
+        if ( pfn_arr_size <= PAGE_SIZE )
+            pfn = alloca(num * sizeof(*pfn));
+        else
+        {
+            pfn = mmap(NULL, pfn_arr_size, PROT_READ | PROT_WRITE,
+                       MAP_PRIVATE | MAP_ANON | MAP_POPULATE, -1, 0);
+            if ( pfn == MAP_FAILED )
+            {
+                PERROR("mmap of pfn array failed");
+                (void)munmap(addr, (unsigned long)num << PAGE_SHIFT);
+                return NULL;
+            }
+        }
+
+        memcpy(pfn, arr, num * sizeof(*arr));
+
+        ioctlx.num = num;
+        ioctlx.dom = dom;
+        ioctlx.addr = (unsigned long)addr;
+        ioctlx.arr = pfn;
+
+        rc = ioctl(fd, IOCTL_PRIVCMD_MMAPBATCH, &ioctlx);
+
+        rc = rc < 0 ? -errno : 0;
+
+        for ( i = 0; i < num; ++i )
+        {
+            switch ( pfn[i] ^ arr[i] )
+            {
+            case 0:
+                err[i] = rc != -ENOENT ? rc : 0;
+                continue;
+            default:
+                err[i] = -EINVAL;
+                continue;
+            case PRIVCMD_MMAPBATCH_PAGED_ERROR:
+                if ( rc != -ENOENT )
+                {
+                    err[i] = rc ?: -EINVAL;
+                    continue;
+                }
+                rc = map_foreign_batch_single(fd, dom, pfn + i,
+                        (unsigned long)addr + ((unsigned long)i<<PAGE_SHIFT));
+                if ( rc < 0 )
+                {
+                    rc = -errno;
+                    break;
+                }
+                rc = -ENOENT;
+                continue;
+            }
+            break;
+        }
+
+        if ( pfn_arr_size > PAGE_SIZE )
+            munmap(pfn, pfn_arr_size);
+
+        if ( rc == -ENOENT && i == num )
+            rc = 0;
+        else if ( rc )
+        {
+            errno = -rc;
+            rc = -1;
+        }
+    }
+
+    if ( rc < 0 )
+    {
+        int saved_errno = errno;
+
+        PERROR("ioctl failed");
+        (void)munmap(addr, (unsigned long)num << PAGE_SHIFT);
+        errno = saved_errno;
+        return NULL;
+    }
+
+    return addr;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxenforeignmemory/minios.c b/tools/libxenforeignmemory/minios.c
new file mode 100644
index 0000000..ac7c0ce
--- /dev/null
+++ b/tools/libxenforeignmemory/minios.c
@@ -0,0 +1,59 @@
+/*
+ * This library 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 of the License.
+ *
+ * This library 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.
+ *
+ * Split out from xc_minios.c
+ *
+ * Copyright 2007-2008 Samuel Thibault <samuel.thibault@eu.citrix.com>.
+ */
+
+#include <mini-os/types.h>
+#include <mini-os/os.h>
+#include <mini-os/mm.h>
+#include <mini-os/lib.h>
+
+#include <errno.h>
+
+#include <sys/mman.h>
+
+#include "private.h"
+
+int osdep_xenforeignmemory_open(xenforeignmemory_handle *fmem)
+{
+    /* No fd required */
+    return 0;
+}
+
+int osdep_xenforeignmemory_close(xenforeignmemory_handle *fmem)
+{
+    return 0;
+}
+
+void *xenforeignmemory_map(xenforeignmemory_handle *fmem,
+			   uint32_t dom, int prot,
+			   const xen_pfn_t *arr, int *err, unsigned int num)
+{
+    unsigned long pt_prot = 0;
+    if (prot & PROT_READ)
+	pt_prot = L1_PROT_RO;
+    if (prot & PROT_WRITE)
+	pt_prot = L1_PROT;
+    return map_frames_ex(arr, num, 1, 0, 1, dom, err, pt_prot);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxenforeignmemory/netbsd.c b/tools/libxenforeignmemory/netbsd.c
new file mode 100644
index 0000000..b2d8b88
--- /dev/null
+++ b/tools/libxenforeignmemory/netbsd.c
@@ -0,0 +1,92 @@
+/******************************************************************************
+ *
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * This library 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 of the License.
+ *
+ * This library 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 <unistd.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#include "private.h"
+
+int osdep_xenforeignmemory_open(xenforeignmemory_handle *fmem)
+{
+    int flags, saved_errno;
+    int fd = open("/kern/xen/privcmd", O_RDWR);
+
+    if ( fd == -1 )
+    {
+        PERROR("Could not obtain handle on privileged command interface");
+        return -1;
+    }
+
+    /* Although we return the file handle as the 'xc handle' the API
+       does not specify / guarentee that this integer is in fact
+       a file handle. Thus we must take responsiblity to ensure
+       it doesn't propagate (ie leak) outside the process */
+    if ( (flags = fcntl(fd, F_GETFD)) < 0 )
+    {
+        PERROR("Could not get file handle flags");
+        goto error;
+    }
+    flags |= FD_CLOEXEC;
+    if ( fcntl(fd, F_SETFD, flags) < 0 )
+    {
+        PERROR("Could not set file handle flags");
+        goto error;
+    }
+
+    fmem->fd = fd;
+    return 0;
+
+ error:
+    saved_errno = errno;
+    close(fd);
+    errno = saved_errno;
+    return -1;
+}
+
+int osdep_xenforeignmemory_close(xenforeignmemory_handle *fmem)
+{
+    int fd = fmem->fd;
+    return close(fd);
+}
+
+void *compat_mapforeign_batch(xenforeignmem_handle *fmem, uint32_t dom,
+                              int prot, xen_pfn_t *arr, int num)
+{
+    int fd = fmem->fd;
+    privcmd_mmapbatch_t ioctlx;
+    void *addr;
+    addr = mmap(NULL, num*XC_PAGE_SIZE, prot, MAP_ANON | MAP_SHARED, -1, 0);
+    if ( addr == MAP_FAILED ) {
+        PERROR("osdep_map_foreign_batch: mmap failed");
+        return NULL;
+    }
+
+    ioctlx.num=num;
+    ioctlx.dom=dom;
+    ioctlx.addr=(unsigned long)addr;
+    ioctlx.arr=arr;
+    if ( ioctl(fd, IOCTL_PRIVCMD_MMAPBATCH, &ioctlx) < 0 )
+    {
+        int saved_errno = errno;
+        PERROR("osdep_map_foreign_batch: ioctl failed");
+        (void)munmap(addr, num*XC_PAGE_SIZE);
+        errno = saved_errno;
+        return NULL;
+    }
+    return addr;
+
+}
diff --git a/tools/libxenforeignmemory/private.h b/tools/libxenforeignmemory/private.h
new file mode 100644
index 0000000..54dd7d5
--- /dev/null
+++ b/tools/libxenforeignmemory/private.h
@@ -0,0 +1,47 @@
+#ifndef XENFOREIGNMEMORY_PRIVATE_H
+#define XENFOREIGNMEMORY_PRIVATE_H
+
+#include <xentoollog.h>
+
+#include <xenforeignmemory.h>
+
+#include <xen/xen.h>
+#include <xen/sys/privcmd.h>
+
+#ifndef PAGE_SHIFT /* Mini-os, Yukk */
+#define PAGE_SHIFT           12
+#endif
+#ifndef __MINIOS__ /* Yukk */
+#define PAGE_SIZE            (1UL << PAGE_SHIFT)
+#define PAGE_MASK            (~(PAGE_SIZE-1))
+#endif
+
+struct xenforeignmemory_handle {
+    xentoollog_logger *logger, *logger_tofree;
+    unsigned flags;
+    int fd;
+};
+
+int osdep_xenforeignmemory_open(xenforeignmemory_handle *fmem);
+int osdep_xenforeignmemory_close(xenforeignmemory_handle *fmem);
+
+#if defined(__NetBSD__) || defined(__sun__)
+/* Strictly compat for those two only only */
+void *compat_mapforeign_batch(xenforeignmem_handle *fmem, uint32_t dom,
+                              int prot, xen_pfn_t *arr, int num);
+#endif
+
+#define PERROR(_f...) \
+	xtl_log(fmem->logger, XTL_ERROR, errno, "xenforeignmemory", _f)
+
+#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxenforeignmemory/solaris.c b/tools/libxenforeignmemory/solaris.c
new file mode 100644
index 0000000..035484b
--- /dev/null
+++ b/tools/libxenforeignmemory/solaris.c
@@ -0,0 +1,95 @@
+/******************************************************************************
+ *
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * This library 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 of the License.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "xc_private.h"
+
+#include <xen/memory.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <malloc.h>
+
+int osdep_xenforeignmemory_open(xenforeignmemory_handle *fmem)
+{
+    int flags, saved_errno;
+    int fd = open("/dev/xen/privcmd", O_RDWR);
+
+    if ( fd == -1 )
+    {
+        PERROR("Could not obtain handle on privileged command interface");
+        return -1;
+    }
+
+    /* Although we return the file handle as the 'xc handle' the API
+       does not specify / guarentee that this integer is in fact
+       a file handle. Thus we must take responsiblity to ensure
+       it doesn't propagate (ie leak) outside the process */
+    if ( (flags = fcntl(fd, F_GETFD)) < 0 )
+    {
+        PERROR("Could not get file handle flags");
+        goto error;
+    }
+    flags |= FD_CLOEXEC;
+    if ( fcntl(fd, F_SETFD, flags) < 0 )
+    {
+        PERROR("Could not set file handle flags");
+        goto error;
+    }
+
+    fmem->fd = fd;
+    return 0;
+
+ error:
+    saved_errno = errno;
+    close(fd);
+    errno = saved_errno;
+    return -1;
+}
+
+int osdep_xenforeignmemory_close(xenforeignmemory_handle *fmem)
+{
+    int fd = fmem->fd;
+    return close(fd);
+}
+
+void *compat_mapforeign_batch(xenforeignmem_handle *fmem, uint32_t dom,
+                              int prot, xen_pfn_t *arr, int num)
+{
+    int fd = fmem->fd;
+    privcmd_mmapbatch_t ioctlx;
+    void *addr;
+    addr = mmap(NULL, num*XC_PAGE_SIZE, prot, MAP_SHARED, fd, 0);
+    if ( addr == MAP_FAILED )
+        return NULL;
+
+    ioctlx.num=num;
+    ioctlx.dom=dom;
+    ioctlx.addr=(unsigned long)addr;
+    ioctlx.arr=arr;
+    if ( ioctl(fd, IOCTL_PRIVCMD_MMAPBATCH, &ioctlx) < 0 )
+    {
+        int saved_errno = errno;
+        PERROR("XXXXXXXX");
+        (void)munmap(addr, num*XC_PAGE_SIZE);
+        errno = saved_errno;
+        return NULL;
+    }
+    return addr;
+
+}
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 4b59cad..101acb0 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -50,6 +50,7 @@
 
 #include <xenevtchn.h>
 #include <xenstore.h>
+#define XC_WANT_COMPAT_MAP_FOREIGN_API
 #include <xenctrl.h>
 #include <xenguest.h>
 
diff --git a/tools/misc/xen-mfndump.c b/tools/misc/xen-mfndump.c
index ceeeaa9..1b22ad7 100644
--- a/tools/misc/xen-mfndump.c
+++ b/tools/misc/xen-mfndump.c
@@ -1,3 +1,4 @@
+#define XC_WANT_COMPAT_MAP_FOREIGN_API
 #include <xenctrl.h>
 #include <xc_private.h>
 #include <xc_core.h>
diff --git a/tools/ocaml/libs/xc/xenctrl_stubs.c b/tools/ocaml/libs/xc/xenctrl_stubs.c
index 9a201ee..1f5aba7 100644
--- a/tools/ocaml/libs/xc/xenctrl_stubs.c
+++ b/tools/ocaml/libs/xc/xenctrl_stubs.c
@@ -29,6 +29,7 @@
 #include <stdint.h>
 #include <string.h>
 
+#define XC_WANT_COMPAT_MAP_FOREIGN_API
 #include <xenctrl.h>
 
 #include "mmap_stubs.h"
diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c
index ee3e1d0..6750ee1 100644
--- a/tools/python/xen/lowlevel/xc/xc.c
+++ b/tools/python/xen/lowlevel/xc/xc.c
@@ -5,6 +5,7 @@
  */
 
 #include <Python.h>
+#define XC_WANT_COMPAT_MAP_FOREIGN_API
 #include <xenctrl.h>
 #include <xenguest.h>
 #include <zlib.h>
@@ -17,7 +18,6 @@
 #include <netdb.h>
 #include <arpa/inet.h>
 
-#include "xenctrl.h"
 #include <xen/elfnote.h>
 #include <xen/tmem.h>
 #include "xc_dom.h"
diff --git a/tools/xenmon/xenbaked.c b/tools/xenmon/xenbaked.c
index 9e2a49b..ad77286 100644
--- a/tools/xenmon/xenbaked.c
+++ b/tools/xenmon/xenbaked.c
@@ -39,6 +39,7 @@
 #include <errno.h>
 #include <signal.h>
 #include <xenevtchn.h>
+#define XC_WANT_COMPAT_MAP_FOREIGN_API
 #include <xenctrl.h>
 #include <xen/xen.h>
 #include <string.h>
diff --git a/tools/xenpaging/pagein.c b/tools/xenpaging/pagein.c
index 18699ec..0ea8680 100644
--- a/tools/xenpaging/pagein.c
+++ b/tools/xenpaging/pagein.c
@@ -1,6 +1,5 @@
 /* Trigger a page-in in a separate thread-of-execution to avoid deadlock */
 #include <pthread.h>
-#include <xc_private.h>
 #include "xenpaging.h"
 
 struct page_in_args {
diff --git a/tools/xenpaging/xenpaging.c b/tools/xenpaging/xenpaging.c
index a819a5b..8a05e98 100644
--- a/tools/xenpaging/xenpaging.c
+++ b/tools/xenpaging/xenpaging.c
@@ -28,7 +28,6 @@
 #include <signal.h>
 #include <unistd.h>
 #include <poll.h>
-#include <xc_private.h>
 #include <xenstore.h>
 #include <getopt.h>
 
diff --git a/tools/xenpaging/xenpaging.h b/tools/xenpaging/xenpaging.h
index 6c12030..3cdd1a8 100644
--- a/tools/xenpaging/xenpaging.h
+++ b/tools/xenpaging/xenpaging.h
@@ -26,6 +26,8 @@
 
 
 #include <xenevtchn.h>
+#define XC_WANT_COMPAT_MAP_FOREIGN_API
+#include <xenctrl.h>
 #include <xc_private.h>
 #include <xen/event_channel.h>
 #include <xen/vm_event.h>
diff --git a/tools/xenstore/xenstored_core.c b/tools/xenstore/xenstored_core.c
index 7f1e489..120fd64 100644
--- a/tools/xenstore/xenstored_core.c
+++ b/tools/xenstore/xenstored_core.c
@@ -51,7 +51,6 @@
 #include "xenstored_watch.h"
 #include "xenstored_transaction.h"
 #include "xenstored_domain.h"
-#include "xenctrl.h"
 #include "tdb.h"
 
 #include "hashtable.h"
diff --git a/tools/xenstore/xenstored_core.h b/tools/xenstore/xenstored_core.h
index 2b01076..e0fa843 100644
--- a/tools/xenstore/xenstored_core.h
+++ b/tools/xenstore/xenstored_core.h
@@ -20,6 +20,7 @@
 #ifndef _XENSTORED_CORE_H
 #define _XENSTORED_CORE_H
 
+#define XC_WANT_COMPAT_MAP_FOREIGN_API
 #include <xenctrl.h>
 #include <xengnttab.h>
 
diff --git a/tools/xentrace/xenctx.c b/tools/xentrace/xenctx.c
index 4ed120a..e647179 100644
--- a/tools/xentrace/xenctx.c
+++ b/tools/xentrace/xenctx.c
@@ -25,7 +25,8 @@
 #include <getopt.h>
 #include <limits.h>
 
-#include "xenctrl.h"
+#define XC_WANT_COMPAT_MAP_FOREIGN_API
+#include <xenctrl.h>
 #include <xen/foreign/x86_32.h>
 #include <xen/foreign/x86_64.h>
 #include <xen/hvm/save.h>
diff --git a/tools/xentrace/xentrace.c b/tools/xentrace/xentrace.c
index f66a77c..28c2b3c 100644
--- a/tools/xentrace/xentrace.c
+++ b/tools/xentrace/xentrace.c
@@ -30,6 +30,7 @@
 #include <xen/xen.h>
 #include <xen/trace.h>
 
+#define XC_WANT_COMPAT_MAP_FOREIGN_API
 #include <xenevtchn.h>
 #include <xenctrl.h>
 
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH XEN v2 15/15] HACK: Add a .config to pull all the right bits.
  2015-07-15 15:46 [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries Ian Campbell
                   ` (13 preceding siblings ...)
  2015-07-15 15:47 ` [PATCH XEN v2 14/15] tools: Refactor foreign memory mapping into libxenforeignmemory Ian Campbell
@ 2015-07-15 15:47 ` Ian Campbell
  2015-07-15 15:47 ` [PATCH QEMUT v2 1/5] qemu-xen-traditional: Use xentoollog as a separate library Ian Campbell
                   ` (12 subsequent siblings)
  27 siblings, 0 replies; 55+ messages in thread
From: Ian Campbell @ 2015-07-15 15:47 UTC (permalink / raw)
  To: ian.jackson, wei.liu2, xen-devel
  Cc: roger.pau, Ian Campbell, stefano.stabellini

---
 .config | 5 +++++
 1 file changed, 5 insertions(+)
 create mode 100644 .config

diff --git a/.config b/.config
new file mode 100644
index 0000000..c2eac60
--- /dev/null
+++ b/.config
@@ -0,0 +1,5 @@
+MINIOS_UPSTREAM_URL := git://xenbits.xen.org/people/ianc/mini-os.git
+MINIOS_UPSTREAM_REVISION := 134bad3e7d1ab2c93019813f607cc703ccef4661
+
+QEMU_TRADITIONAL_URL := git://xenbits.xen.org/people/ianc/qemu-xen-unstable.git
+QEMU_TRADITIONAL_REVISION := cdd8d90e3f631092dc81f5dd4b68f384c9ccf1cc
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH QEMUT v2 1/5] qemu-xen-traditional: Use xentoollog as a separate library
  2015-07-15 15:46 [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries Ian Campbell
                   ` (14 preceding siblings ...)
  2015-07-15 15:47 ` [PATCH XEN v2 15/15] HACK: Add a .config to pull all the right bits Ian Campbell
@ 2015-07-15 15:47 ` Ian Campbell
  2015-07-15 15:47 ` [PATCH QEMUT v2 2/5] qemu-xen-traditional: Use libxenevtchn Ian Campbell
                   ` (11 subsequent siblings)
  27 siblings, 0 replies; 55+ messages in thread
From: Ian Campbell @ 2015-07-15 15:47 UTC (permalink / raw)
  To: ian.jackson, wei.liu2, xen-devel
  Cc: roger.pau, Ian Campbell, stefano.stabellini

This has been split out of libxenctrl, so the build needs to be able
to find the header and the library. QEMU does not use xtl_* itself so
-rpath-link is sufficient to allow linking to libxenctrl.so (which
links against libxentoollog).

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
---
 xen-hooks.mak | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/xen-hooks.mak b/xen-hooks.mak
index bc7f1f1..2e53c04 100644
--- a/xen-hooks.mak
+++ b/xen-hooks.mak
@@ -1,3 +1,4 @@
+CPPFLAGS+= -I$(XEN_ROOT)/tools/libxentoollog/include
 CPPFLAGS+= -I$(XEN_ROOT)/tools/libxc/include
 CPPFLAGS+= -I$(XEN_ROOT)/tools/xenstore/include
 CPPFLAGS+= -I$(XEN_ROOT)/tools/include
@@ -19,6 +20,7 @@ CFLAGS += $(CMDLINE_CFLAGS)
 
 LIBS += -L$(XEN_ROOT)/tools/libxc -lxenctrl -lxenguest
 LIBS += -L$(XEN_ROOT)/tools/xenstore -lxenstore
+LIBS += -Wl,-rpath-link=$(XEN_ROOT)/tools/libxentoollog
 
 LDFLAGS := $(CFLAGS) $(LDFLAGS)
 
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH QEMUT v2 2/5] qemu-xen-traditional: Use libxenevtchn
  2015-07-15 15:46 [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries Ian Campbell
                   ` (15 preceding siblings ...)
  2015-07-15 15:47 ` [PATCH QEMUT v2 1/5] qemu-xen-traditional: Use xentoollog as a separate library Ian Campbell
@ 2015-07-15 15:47 ` Ian Campbell
  2015-07-15 15:47 ` [PATCH QEMUT v2 3/5] qemu-xen-traditional: Use libxengnttab Ian Campbell
                   ` (10 subsequent siblings)
  27 siblings, 0 replies; 55+ messages in thread
From: Ian Campbell @ 2015-07-15 15:47 UTC (permalink / raw)
  To: ian.jackson, wei.liu2, xen-devel
  Cc: roger.pau, Ian Campbell, stefano.stabellini

/dev/xen/evtchn related wrappers have been moved out of libxenctrl
into their own library.

Note that i386-dm/helper2.c's xc_interface * was always really an
xc_evtchn *, it's just they used to be typedefs to the same thing...

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
---
 hw/xen_backend.c  | 26 +++++++++++++-------------
 hw/xen_backend.h  |  2 +-
 hw/xen_common.h   |  1 +
 i386-dm/helper2.c | 19 ++++++++++---------
 xen-hooks.mak     |  2 ++
 5 files changed, 27 insertions(+), 23 deletions(-)

diff --git a/hw/xen_backend.c b/hw/xen_backend.c
index 92b3506..40f6887 100644
--- a/hw/xen_backend.c
+++ b/hw/xen_backend.c
@@ -208,19 +208,19 @@ static struct XenDevice *xen_be_get_xendev(const char *type, int dom, int dev,
     xendev->debug      = debug;
     xendev->local_port = -1;
 
-    xendev->evtchndev = xc_evtchn_open(NULL, 0);
+    xendev->evtchndev = xenevtchn_open(NULL, 0);
     if (xendev->evtchndev == NULL) {
 	xen_be_printf(NULL, 0, "can't open evtchn device\n");
 	qemu_free(xendev);
 	return NULL;
     }
-    fcntl(xc_evtchn_fd(xendev->evtchndev), F_SETFD, FD_CLOEXEC);
+    fcntl(xenevtchn_fd(xendev->evtchndev), F_SETFD, FD_CLOEXEC);
 
     if (ops->flags & DEVOPS_FLAG_NEED_GNTDEV) {
 	xendev->gnttabdev = xc_gnttab_open(NULL, 0);
 	if (xendev->gnttabdev == NULL) {
 	    xen_be_printf(NULL, 0, "can't open gnttab device\n");
-	    xc_evtchn_close(xendev->evtchndev);
+	    xenevtchn_close(xendev->evtchndev);
 	    qemu_free(xendev);
 	    return NULL;
 	}
@@ -268,7 +268,7 @@ static struct XenDevice *xen_be_del_xendev(int dom, int dev)
 	}
 
 	if (xendev->evtchndev != NULL)
-	    xc_evtchn_close(xendev->evtchndev);
+	    xenevtchn_close(xendev->evtchndev);
 	if (xendev->gnttabdev != NULL)
 	    xc_gnttab_close(xendev->gnttabdev);
 
@@ -630,13 +630,13 @@ static void xen_be_evtchn_event(void *opaque)
     struct XenDevice *xendev = opaque;
     evtchn_port_t port;
 
-    port = xc_evtchn_pending(xendev->evtchndev);
+    port = xenevtchn_pending(xendev->evtchndev);
     if (port != xendev->local_port) {
-	xen_be_printf(xendev, 0, "xc_evtchn_pending returned %d (expected %d)\n",
+	xen_be_printf(xendev, 0, "xenevtchn_pending returned %d (expected %d)\n",
 		      port, xendev->local_port);
 	return;
     }
-    xc_evtchn_unmask(xendev->evtchndev, port);
+    xenevtchn_unmask(xendev->evtchndev, port);
 
     if (xendev->ops->event)
 	xendev->ops->event(xendev);
@@ -683,14 +683,14 @@ int xen_be_bind_evtchn(struct XenDevice *xendev)
 {
     if (xendev->local_port != -1)
 	return 0;
-    xendev->local_port = xc_evtchn_bind_interdomain
+    xendev->local_port = xenevtchn_bind_interdomain
 	(xendev->evtchndev, xendev->dom, xendev->remote_port);
     if (xendev->local_port == -1) {
-	xen_be_printf(xendev, 0, "xc_evtchn_bind_interdomain failed\n");
+	xen_be_printf(xendev, 0, "xenevtchn_bind_interdomain failed\n");
 	return -1;
     }
     xen_be_printf(xendev, 2, "bind evtchn port %d\n", xendev->local_port);
-    qemu_set_fd_handler(xc_evtchn_fd(xendev->evtchndev),
+    qemu_set_fd_handler(xenevtchn_fd(xendev->evtchndev),
 			xen_be_evtchn_event, NULL, xendev);
     return 0;
 }
@@ -699,15 +699,15 @@ void xen_be_unbind_evtchn(struct XenDevice *xendev)
 {
     if (xendev->local_port == -1)
 	return;
-    qemu_set_fd_handler(xc_evtchn_fd(xendev->evtchndev), NULL, NULL, NULL);
-    xc_evtchn_unbind(xendev->evtchndev, xendev->local_port);
+    qemu_set_fd_handler(xenevtchn_fd(xendev->evtchndev), NULL, NULL, NULL);
+    xenevtchn_unbind(xendev->evtchndev, xendev->local_port);
     xen_be_printf(xendev, 2, "unbind evtchn port %d\n", xendev->local_port);
     xendev->local_port = -1;
 }
 
 int xen_be_send_notify(struct XenDevice *xendev)
 {
-    return xc_evtchn_notify(xendev->evtchndev, xendev->local_port);
+    return xenevtchn_notify(xendev->evtchndev, xendev->local_port);
 }
 
 /*
diff --git a/hw/xen_backend.h b/hw/xen_backend.h
index e421391..60f18f8 100644
--- a/hw/xen_backend.h
+++ b/hw/xen_backend.h
@@ -44,7 +44,7 @@ struct XenDevice {
     int                remote_port;
     int                local_port;
 
-    xc_evtchn          *evtchndev;
+    xenevtchn_handle   *evtchndev;
     xc_gnttab          *gnttabdev;
 
     struct XenDevOps   *ops;
diff --git a/hw/xen_common.h b/hw/xen_common.h
index a615052..cee908f 100644
--- a/hw/xen_common.h
+++ b/hw/xen_common.h
@@ -4,6 +4,7 @@
 #include <stddef.h>
 #include <inttypes.h>
 
+#include <xenevtchn.h>
 #include <xenctrl.h>
 #include <xenstore.h>
 #include <xen/io/xenbus.h>
diff --git a/i386-dm/helper2.c b/i386-dm/helper2.c
index 63a938b..e4df0d7 100644
--- a/i386-dm/helper2.c
+++ b/i386-dm/helper2.c
@@ -48,6 +48,7 @@
 #include <limits.h>
 #include <fcntl.h>
 
+#include <xenevtchn.h>
 #include <xenctrl.h>
 #include <xen/hvm/ioreq.h>
 #include <xen/hvm/hvm_info_table.h>
@@ -104,7 +105,7 @@ buffered_iopage_t *buffered_io_page = NULL;
 QEMUTimer *buffered_io_timer;
 
 /* the evtchn fd for polling */
-xc_interface *xce_handle = NULL;
+xenevtchn_handle *xce_handle = NULL;
 
 /* which vcpu we are serving */
 int send_vcpu = 0;
@@ -141,7 +142,7 @@ CPUX86State *cpu_x86_init(const char *cpu_model)
 
         cpu_single_env = env;
 
-        xce_handle = xc_evtchn_open(NULL, 0);
+        xce_handle = xenevtchn_open(NULL, 0);
         if (xce_handle == NULL) {
             perror("open");
             return NULL;
@@ -149,7 +150,7 @@ CPUX86State *cpu_x86_init(const char *cpu_model)
 
         /* FIXME: how about if we overflow the page here? */
         for (i = 0; i < vcpus; i++) {
-            rc = xc_evtchn_bind_interdomain(
+            rc = xenevtchn_bind_interdomain(
                 xce_handle, domid, shared_page->vcpu_ioreq[i].vp_eport);
             if (rc == -1) {
                 fprintf(logfile, "bind interdomain ioctl error %d\n", errno);
@@ -164,7 +165,7 @@ CPUX86State *cpu_x86_init(const char *cpu_model)
                     errno);
             return NULL;
         }
-        rc = xc_evtchn_bind_interdomain(xce_handle, domid, (uint32_t)bufioreq_evtchn);
+        rc = xenevtchn_bind_interdomain(xce_handle, domid, (uint32_t)bufioreq_evtchn);
         if (rc == -1) {
             fprintf(logfile, "bind interdomain ioctl error %d\n", errno);
             return NULL;
@@ -278,7 +279,7 @@ static ioreq_t *cpu_get_ioreq(void)
     int i;
     evtchn_port_t port;
 
-    port = xc_evtchn_pending(xce_handle);
+    port = xenevtchn_pending(xce_handle);
     if (port == bufioreq_local_port) {
         qemu_mod_timer(buffered_io_timer,
                 BUFFER_IO_MAX_DELAY + qemu_get_clock(rt_clock));
@@ -296,7 +297,7 @@ static ioreq_t *cpu_get_ioreq(void)
         }
 
         // unmask the wanted port again
-        xc_evtchn_unmask(xce_handle, port);
+        xenevtchn_unmask(xce_handle, port);
 
         //get the io packet from shared memory
         send_vcpu = i;
@@ -531,7 +532,7 @@ static void handle_buffered_io(void *opaque)
                 BUFFER_IO_MAX_DELAY + qemu_get_clock(rt_clock));
     } else {
         qemu_del_timer(buffered_io_timer);
-        xc_evtchn_unmask(xce_handle, bufioreq_local_port);
+        xenevtchn_unmask(xce_handle, bufioreq_local_port);
     }
 }
 
@@ -575,7 +576,7 @@ static void cpu_handle_ioreq(void *opaque)
 	}
 
         req->state = STATE_IORESP_READY;
-        xc_evtchn_notify(xce_handle, ioreq_local_port[send_vcpu]);
+        xenevtchn_notify(xce_handle, ioreq_local_port[send_vcpu]);
     }
 }
 
@@ -584,7 +585,7 @@ int xen_pause_requested;
 int main_loop(void)
 {
     CPUState *env = cpu_single_env;
-    int evtchn_fd = xce_handle == NULL ? -1 : xc_evtchn_fd(xce_handle);
+    int evtchn_fd = xce_handle == NULL ? -1 : xenevtchn_fd(xce_handle);
     char *qemu_file;
     fd_set fds;
 
diff --git a/xen-hooks.mak b/xen-hooks.mak
index 2e53c04..ec5fbab 100644
--- a/xen-hooks.mak
+++ b/xen-hooks.mak
@@ -1,4 +1,5 @@
 CPPFLAGS+= -I$(XEN_ROOT)/tools/libxentoollog/include
+CPPFLAGS+= -I$(XEN_ROOT)/tools/libxenevtchn/include
 CPPFLAGS+= -I$(XEN_ROOT)/tools/libxc/include
 CPPFLAGS+= -I$(XEN_ROOT)/tools/xenstore/include
 CPPFLAGS+= -I$(XEN_ROOT)/tools/include
@@ -18,6 +19,7 @@ endif
 
 CFLAGS += $(CMDLINE_CFLAGS)
 
+LIBS += -L$(XEN_ROOT)/tools/libxenevtchn -lxenevtchn
 LIBS += -L$(XEN_ROOT)/tools/libxc -lxenctrl -lxenguest
 LIBS += -L$(XEN_ROOT)/tools/xenstore -lxenstore
 LIBS += -Wl,-rpath-link=$(XEN_ROOT)/tools/libxentoollog
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH QEMUT v2 3/5] qemu-xen-traditional: Use libxengnttab
  2015-07-15 15:46 [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries Ian Campbell
                   ` (16 preceding siblings ...)
  2015-07-15 15:47 ` [PATCH QEMUT v2 2/5] qemu-xen-traditional: Use libxenevtchn Ian Campbell
@ 2015-07-15 15:47 ` Ian Campbell
  2015-07-15 15:47 ` [PATCH QEMUT v2 4/5] qemu-xen-traditional: Add libxencall to rpath-link Ian Campbell
                   ` (9 subsequent siblings)
  27 siblings, 0 replies; 55+ messages in thread
From: Ian Campbell @ 2015-07-15 15:47 UTC (permalink / raw)
  To: ian.jackson, wei.liu2, xen-devel
  Cc: roger.pau, Ian Campbell, stefano.stabellini

/dev/xen/gntdev related wrappers have been moved out of libxenctrl
into their own library.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
---
 hw/xen_backend.c |  4 ++--
 hw/xen_backend.h |  2 +-
 hw/xen_common.h  |  1 +
 hw/xen_console.c |  4 ++--
 hw/xen_disk.c    | 24 ++++++++++++------------
 xen-hooks.mak    |  2 ++
 6 files changed, 20 insertions(+), 17 deletions(-)

diff --git a/hw/xen_backend.c b/hw/xen_backend.c
index 40f6887..97d25da 100644
--- a/hw/xen_backend.c
+++ b/hw/xen_backend.c
@@ -217,7 +217,7 @@ static struct XenDevice *xen_be_get_xendev(const char *type, int dom, int dev,
     fcntl(xenevtchn_fd(xendev->evtchndev), F_SETFD, FD_CLOEXEC);
 
     if (ops->flags & DEVOPS_FLAG_NEED_GNTDEV) {
-	xendev->gnttabdev = xc_gnttab_open(NULL, 0);
+	xendev->gnttabdev = xengnttab_open(NULL, 0);
 	if (xendev->gnttabdev == NULL) {
 	    xen_be_printf(NULL, 0, "can't open gnttab device\n");
 	    xenevtchn_close(xendev->evtchndev);
@@ -270,7 +270,7 @@ static struct XenDevice *xen_be_del_xendev(int dom, int dev)
 	if (xendev->evtchndev != NULL)
 	    xenevtchn_close(xendev->evtchndev);
 	if (xendev->gnttabdev != NULL)
-	    xc_gnttab_close(xendev->gnttabdev);
+	    xengnttab_close(xendev->gnttabdev);
 
 	TAILQ_REMOVE(&xendevs, xendev, next);
 	qemu_free(xendev);
diff --git a/hw/xen_backend.h b/hw/xen_backend.h
index 60f18f8..ba1e12f 100644
--- a/hw/xen_backend.h
+++ b/hw/xen_backend.h
@@ -45,7 +45,7 @@ struct XenDevice {
     int                local_port;
 
     xenevtchn_handle   *evtchndev;
-    xc_gnttab          *gnttabdev;
+    xengnttab_handle          *gnttabdev;
 
     struct XenDevOps   *ops;
     TAILQ_ENTRY(XenDevice) next;
diff --git a/hw/xen_common.h b/hw/xen_common.h
index cee908f..cc48892 100644
--- a/hw/xen_common.h
+++ b/hw/xen_common.h
@@ -5,6 +5,7 @@
 #include <inttypes.h>
 
 #include <xenevtchn.h>
+#include <xengnttab.h>
 #include <xenctrl.h>
 #include <xenstore.h>
 #include <xen/io/xenbus.h>
diff --git a/hw/xen_console.c b/hw/xen_console.c
index 80beb31..76c4e93 100644
--- a/hw/xen_console.c
+++ b/hw/xen_console.c
@@ -230,7 +230,7 @@ static int con_initialise(struct XenDevice *xendev)
                                           PROT_READ|PROT_WRITE,
                                           con->ring_ref);
     else
-        con->sring = xc_gnttab_map_grant_ref(xendev->gnttabdev, con->xendev.dom,
+        con->sring = xengnttab_map_grant_ref(xendev->gnttabdev, con->xendev.dom,
                                              con->ring_ref,
                                              PROT_READ|PROT_WRITE);
     if (!con->sring)
@@ -263,7 +263,7 @@ static void con_disconnect(struct XenDevice *xendev)
         if (!xendev->gnttabdev)
 	    munmap(con->sring, XC_PAGE_SIZE);
         else
-            xc_gnttab_munmap(xendev->gnttabdev, con->sring, 1);
+            xengnttab_munmap(xendev->gnttabdev, con->sring, 1);
 	con->sring = NULL;
     }
 }
diff --git a/hw/xen_disk.c b/hw/xen_disk.c
index 250d806..6ccf073 100644
--- a/hw/xen_disk.c
+++ b/hw/xen_disk.c
@@ -266,7 +266,7 @@ err:
 
 static void ioreq_unmap(struct ioreq *ioreq)
 {
-    xc_gnttab *gnt = ioreq->blkdev->xendev.gnttabdev;
+    xengnttab_handle *gnt = ioreq->blkdev->xendev.gnttabdev;
     int i;
 
     if (ioreq->v.niov == 0)
@@ -274,8 +274,8 @@ static void ioreq_unmap(struct ioreq *ioreq)
     if (batch_maps) {
 	if (!ioreq->pages)
 	    return;
-	if (xc_gnttab_munmap(gnt, ioreq->pages, ioreq->v.niov) != 0)
-	    xen_be_printf(&ioreq->blkdev->xendev, 0, "xc_gnttab_munmap failed: %s\n",
+	if (xengnttab_munmap(gnt, ioreq->pages, ioreq->v.niov) != 0)
+	    xen_be_printf(&ioreq->blkdev->xendev, 0, "xengnttab_munmap failed: %s\n",
 			  strerror(errno));
 	ioreq->blkdev->cnt_map -= ioreq->v.niov;
 	ioreq->pages = NULL;
@@ -283,8 +283,8 @@ static void ioreq_unmap(struct ioreq *ioreq)
 	for (i = 0; i < ioreq->v.niov; i++) {
 	    if (!ioreq->page[i])
 		continue;
-	    if (xc_gnttab_munmap(gnt, ioreq->page[i], 1) != 0)
-		xen_be_printf(&ioreq->blkdev->xendev, 0, "xc_gnttab_munmap failed: %s\n",
+	    if (xengnttab_munmap(gnt, ioreq->page[i], 1) != 0)
+		xen_be_printf(&ioreq->blkdev->xendev, 0, "xengnttab_munmap failed: %s\n",
 			      strerror(errno));
 	    ioreq->blkdev->cnt_map--;
 	    ioreq->page[i] = NULL;
@@ -294,13 +294,13 @@ static void ioreq_unmap(struct ioreq *ioreq)
 
 static int ioreq_map(struct ioreq *ioreq)
 {
-    xc_gnttab *gnt = ioreq->blkdev->xendev.gnttabdev;
+    xengnttab_handle *gnt = ioreq->blkdev->xendev.gnttabdev;
     int i;
 
     if (ioreq->v.niov == 0)
         return 0;
     if (batch_maps) {
-	ioreq->pages = xc_gnttab_map_grant_refs
+	ioreq->pages = xengnttab_map_grant_refs
 	    (gnt, ioreq->v.niov, ioreq->domids, ioreq->refs, ioreq->prot);
 	if (ioreq->pages == NULL) {
 	    xen_be_printf(&ioreq->blkdev->xendev, 0,
@@ -314,7 +314,7 @@ static int ioreq_map(struct ioreq *ioreq)
 	ioreq->blkdev->cnt_map += ioreq->v.niov;
     } else  {
 	for (i = 0; i < ioreq->v.niov; i++) {
-	    ioreq->page[i] = xc_gnttab_map_grant_ref
+	    ioreq->page[i] = xengnttab_map_grant_ref
 		(gnt, ioreq->domids[i], ioreq->refs[i], ioreq->prot);
 	    if (ioreq->page[i] == NULL) {
 		xen_be_printf(&ioreq->blkdev->xendev, 0,
@@ -611,9 +611,9 @@ static void blk_alloc(struct XenDevice *xendev)
     blkdev->bh = qemu_bh_new(blk_bh, blkdev);
     if (xen_mode != XEN_EMULATE)
         batch_maps = 1;
-    if (xc_gnttab_set_max_grants(xendev->gnttabdev,
+    if (xengnttab_set_max_grants(xendev->gnttabdev,
             MAX_GRANTS(max_requests, BLKIF_MAX_SEGMENTS_PER_REQUEST)) < 0) {
-        xen_be_printf(xendev, 0, "xc_gnttab_set_max_grants failed: %s\n",
+        xen_be_printf(xendev, 0, "xengnttab_set_max_grants failed: %s\n",
                       strerror(errno));
     }
 }
@@ -734,7 +734,7 @@ static int blk_connect(struct XenDevice *xendev)
             blkdev->protocol = BLKIF_PROTOCOL_X86_64;
     }
 
-    blkdev->sring = xc_gnttab_map_grant_ref(blkdev->xendev.gnttabdev,
+    blkdev->sring = xengnttab_map_grant_ref(blkdev->xendev.gnttabdev,
 					    blkdev->xendev.dom,
 					    blkdev->ring_ref,
 					    PROT_READ | PROT_WRITE);
@@ -787,7 +787,7 @@ static void blk_disconnect(struct XenDevice *xendev)
     xen_be_unbind_evtchn(&blkdev->xendev);
 
     if (blkdev->sring) {
-	xc_gnttab_munmap(blkdev->xendev.gnttabdev, blkdev->sring, 1);
+	xengnttab_munmap(blkdev->xendev.gnttabdev, blkdev->sring, 1);
 	blkdev->cnt_map--;
 	blkdev->sring = NULL;
     }
diff --git a/xen-hooks.mak b/xen-hooks.mak
index ec5fbab..67f44ba 100644
--- a/xen-hooks.mak
+++ b/xen-hooks.mak
@@ -1,5 +1,6 @@
 CPPFLAGS+= -I$(XEN_ROOT)/tools/libxentoollog/include
 CPPFLAGS+= -I$(XEN_ROOT)/tools/libxenevtchn/include
+CPPFLAGS+= -I$(XEN_ROOT)/tools/libxengnttab/include
 CPPFLAGS+= -I$(XEN_ROOT)/tools/libxc/include
 CPPFLAGS+= -I$(XEN_ROOT)/tools/xenstore/include
 CPPFLAGS+= -I$(XEN_ROOT)/tools/include
@@ -20,6 +21,7 @@ endif
 CFLAGS += $(CMDLINE_CFLAGS)
 
 LIBS += -L$(XEN_ROOT)/tools/libxenevtchn -lxenevtchn
+LIBS += -L$(XEN_ROOT)/tools/libxengnttab -lxengnttab
 LIBS += -L$(XEN_ROOT)/tools/libxc -lxenctrl -lxenguest
 LIBS += -L$(XEN_ROOT)/tools/xenstore -lxenstore
 LIBS += -Wl,-rpath-link=$(XEN_ROOT)/tools/libxentoollog
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH QEMUT v2 4/5] qemu-xen-traditional: Add libxencall to rpath-link
  2015-07-15 15:46 [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries Ian Campbell
                   ` (17 preceding siblings ...)
  2015-07-15 15:47 ` [PATCH QEMUT v2 3/5] qemu-xen-traditional: Use libxengnttab Ian Campbell
@ 2015-07-15 15:47 ` Ian Campbell
  2015-07-15 15:47 ` [PATCH QEMUT v2 5/5] qemu-xen-traditional: Add libxenforeignmemory " Ian Campbell
                   ` (8 subsequent siblings)
  27 siblings, 0 replies; 55+ messages in thread
From: Ian Campbell @ 2015-07-15 15:47 UTC (permalink / raw)
  To: ian.jackson, wei.liu2, xen-devel
  Cc: roger.pau, Ian Campbell, stefano.stabellini

libxenctrl links against this library

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
---
 xen-hooks.mak | 1 +
 1 file changed, 1 insertion(+)

diff --git a/xen-hooks.mak b/xen-hooks.mak
index 67f44ba..42a72d8 100644
--- a/xen-hooks.mak
+++ b/xen-hooks.mak
@@ -25,6 +25,7 @@ LIBS += -L$(XEN_ROOT)/tools/libxengnttab -lxengnttab
 LIBS += -L$(XEN_ROOT)/tools/libxc -lxenctrl -lxenguest
 LIBS += -L$(XEN_ROOT)/tools/xenstore -lxenstore
 LIBS += -Wl,-rpath-link=$(XEN_ROOT)/tools/libxentoollog
+LIBS += -Wl,-rpath-link=$(XEN_ROOT)/tools/libxencall
 
 LDFLAGS := $(CFLAGS) $(LDFLAGS)
 
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH QEMUT v2 5/5] qemu-xen-traditional: Add libxenforeignmemory to rpath-link
  2015-07-15 15:46 [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries Ian Campbell
                   ` (18 preceding siblings ...)
  2015-07-15 15:47 ` [PATCH QEMUT v2 4/5] qemu-xen-traditional: Add libxencall to rpath-link Ian Campbell
@ 2015-07-15 15:47 ` Ian Campbell
  2015-07-15 15:48 ` [PATCH MINI-OS v2 1/5] mini-os: Include libxentoollog with libxc Ian Campbell
                   ` (7 subsequent siblings)
  27 siblings, 0 replies; 55+ messages in thread
From: Ian Campbell @ 2015-07-15 15:47 UTC (permalink / raw)
  To: ian.jackson, wei.liu2, xen-devel
  Cc: roger.pau, Ian Campbell, stefano.stabellini

libxenctrl links against this library.

Also, request the compat xc_map_foreign API from libxc.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
---
 xen-hooks.mak | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/xen-hooks.mak b/xen-hooks.mak
index 42a72d8..b6dfc4a 100644
--- a/xen-hooks.mak
+++ b/xen-hooks.mak
@@ -1,6 +1,7 @@
 CPPFLAGS+= -I$(XEN_ROOT)/tools/libxentoollog/include
 CPPFLAGS+= -I$(XEN_ROOT)/tools/libxenevtchn/include
 CPPFLAGS+= -I$(XEN_ROOT)/tools/libxengnttab/include
+CPPFLAGS+= -DXC_WANT_COMPAT_MAP_FOREIGN_API
 CPPFLAGS+= -I$(XEN_ROOT)/tools/libxc/include
 CPPFLAGS+= -I$(XEN_ROOT)/tools/xenstore/include
 CPPFLAGS+= -I$(XEN_ROOT)/tools/include
@@ -26,6 +27,7 @@ LIBS += -L$(XEN_ROOT)/tools/libxc -lxenctrl -lxenguest
 LIBS += -L$(XEN_ROOT)/tools/xenstore -lxenstore
 LIBS += -Wl,-rpath-link=$(XEN_ROOT)/tools/libxentoollog
 LIBS += -Wl,-rpath-link=$(XEN_ROOT)/tools/libxencall
+LIBS += -Wl,-rpath-link=$(XEN_ROOT)/tools/libxenforeignmemory
 
 LDFLAGS := $(CFLAGS) $(LDFLAGS)
 
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH MINI-OS v2 1/5] mini-os: Include libxentoollog with libxc
  2015-07-15 15:46 [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries Ian Campbell
                   ` (19 preceding siblings ...)
  2015-07-15 15:47 ` [PATCH QEMUT v2 5/5] qemu-xen-traditional: Add libxenforeignmemory " Ian Campbell
@ 2015-07-15 15:48 ` Ian Campbell
  2015-07-15 15:48 ` [PATCH MINI-OS v2 2/5] mini-os: Include libxenevtchn " Ian Campbell
                   ` (6 subsequent siblings)
  27 siblings, 0 replies; 55+ messages in thread
From: Ian Campbell @ 2015-07-15 15:48 UTC (permalink / raw)
  To: ian.jackson, wei.liu2, xen-devel
  Cc: minios-devel, roger.pau, Ian Campbell, stefano.stabellini

libxentoollog has just been split out from libxc. From mini-os's point
of view we don't care about the distinction, so keep things simple by
just including libxentoollog if libxc is enabled.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
---
 Makefile | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Makefile b/Makefile
index 2cb5e51..757bd70 100644
--- a/Makefile
+++ b/Makefile
@@ -165,6 +165,7 @@ OBJS := $(filter-out $(OBJ_DIR)/lwip%.o $(LWO), $(OBJS))
 
 ifeq ($(libc),y)
 ifeq ($(CONFIG_XC),y)
+APP_LDLIBS += -L$(XEN_ROOT)/stubdom/libxentoollog-$(MINIOS_TARGET_ARCH) -whole-archive -lxentoollog -no-whole-archive
 APP_LDLIBS += -L$(XEN_ROOT)/stubdom/libxc-$(MINIOS_TARGET_ARCH) -whole-archive -lxenguest -lxenctrl -no-whole-archive
 endif
 APP_LDLIBS += -lpci
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH MINI-OS v2 2/5] mini-os: Include libxenevtchn with libxc
  2015-07-15 15:46 [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries Ian Campbell
                   ` (20 preceding siblings ...)
  2015-07-15 15:48 ` [PATCH MINI-OS v2 1/5] mini-os: Include libxentoollog with libxc Ian Campbell
@ 2015-07-15 15:48 ` Ian Campbell
  2015-07-15 15:48 ` [PATCH MINI-OS v2 3/5] mini-os: Include libxengnttab " Ian Campbell
                   ` (5 subsequent siblings)
  27 siblings, 0 replies; 55+ messages in thread
From: Ian Campbell @ 2015-07-15 15:48 UTC (permalink / raw)
  To: ian.jackson, wei.liu2, xen-devel
  Cc: minios-devel, roger.pau, Ian Campbell, stefano.stabellini

libxenevtchn has just been split out from libxc. From mini-os's point
of view we don't care about the distinction, so keep things simple by
just including libxenevtchn if libxc is enabled.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
---
 Makefile | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Makefile b/Makefile
index 757bd70..66ed510 100644
--- a/Makefile
+++ b/Makefile
@@ -166,6 +166,7 @@ OBJS := $(filter-out $(OBJ_DIR)/lwip%.o $(LWO), $(OBJS))
 ifeq ($(libc),y)
 ifeq ($(CONFIG_XC),y)
 APP_LDLIBS += -L$(XEN_ROOT)/stubdom/libxentoollog-$(MINIOS_TARGET_ARCH) -whole-archive -lxentoollog -no-whole-archive
+APP_LDLIBS += -L$(XEN_ROOT)/stubdom/libxenevtchn-$(MINIOS_TARGET_ARCH) -whole-archive -lxenevtchn -no-whole-archive
 APP_LDLIBS += -L$(XEN_ROOT)/stubdom/libxc-$(MINIOS_TARGET_ARCH) -whole-archive -lxenguest -lxenctrl -no-whole-archive
 endif
 APP_LDLIBS += -lpci
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH MINI-OS v2 3/5] mini-os: Include libxengnttab with libxc
  2015-07-15 15:46 [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries Ian Campbell
                   ` (21 preceding siblings ...)
  2015-07-15 15:48 ` [PATCH MINI-OS v2 2/5] mini-os: Include libxenevtchn " Ian Campbell
@ 2015-07-15 15:48 ` Ian Campbell
  2015-07-15 15:48 ` [PATCH MINI-OS v2 4/5] mini-os: Include libxencall " Ian Campbell
                   ` (4 subsequent siblings)
  27 siblings, 0 replies; 55+ messages in thread
From: Ian Campbell @ 2015-07-15 15:48 UTC (permalink / raw)
  To: ian.jackson, wei.liu2, xen-devel
  Cc: minios-devel, roger.pau, Ian Campbell, stefano.stabellini

libxengnttab has just been split out from libxc. From mini-os's point
of view we don't care about the distinction, so keep things simple by
just including libxengnttab if libxc is enabled.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
---
 Makefile | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Makefile b/Makefile
index 66ed510..5e67e6c 100644
--- a/Makefile
+++ b/Makefile
@@ -167,6 +167,7 @@ ifeq ($(libc),y)
 ifeq ($(CONFIG_XC),y)
 APP_LDLIBS += -L$(XEN_ROOT)/stubdom/libxentoollog-$(MINIOS_TARGET_ARCH) -whole-archive -lxentoollog -no-whole-archive
 APP_LDLIBS += -L$(XEN_ROOT)/stubdom/libxenevtchn-$(MINIOS_TARGET_ARCH) -whole-archive -lxenevtchn -no-whole-archive
+APP_LDLIBS += -L$(XEN_ROOT)/stubdom/libxengnttab-$(MINIOS_TARGET_ARCH) -whole-archive -lxengnttab -no-whole-archive
 APP_LDLIBS += -L$(XEN_ROOT)/stubdom/libxc-$(MINIOS_TARGET_ARCH) -whole-archive -lxenguest -lxenctrl -no-whole-archive
 endif
 APP_LDLIBS += -lpci
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH MINI-OS v2 4/5] mini-os: Include libxencall with libxc
  2015-07-15 15:46 [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries Ian Campbell
                   ` (22 preceding siblings ...)
  2015-07-15 15:48 ` [PATCH MINI-OS v2 3/5] mini-os: Include libxengnttab " Ian Campbell
@ 2015-07-15 15:48 ` Ian Campbell
  2015-07-15 15:48 ` [PATCH MINI-OS v2 5/5] mini-os: Include libxenforeignmemory " Ian Campbell
                   ` (3 subsequent siblings)
  27 siblings, 0 replies; 55+ messages in thread
From: Ian Campbell @ 2015-07-15 15:48 UTC (permalink / raw)
  To: ian.jackson, wei.liu2, xen-devel
  Cc: minios-devel, roger.pau, Ian Campbell, stefano.stabellini

libxencall has just been split out from libxc. From mini-os's point
of view we don't care about the distinction, so keep things simple by
just including libxencall if libxc is enabled.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
---
 Makefile | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Makefile b/Makefile
index 5e67e6c..835c47b 100644
--- a/Makefile
+++ b/Makefile
@@ -168,6 +168,7 @@ ifeq ($(CONFIG_XC),y)
 APP_LDLIBS += -L$(XEN_ROOT)/stubdom/libxentoollog-$(MINIOS_TARGET_ARCH) -whole-archive -lxentoollog -no-whole-archive
 APP_LDLIBS += -L$(XEN_ROOT)/stubdom/libxenevtchn-$(MINIOS_TARGET_ARCH) -whole-archive -lxenevtchn -no-whole-archive
 APP_LDLIBS += -L$(XEN_ROOT)/stubdom/libxengnttab-$(MINIOS_TARGET_ARCH) -whole-archive -lxengnttab -no-whole-archive
+APP_LDLIBS += -L$(XEN_ROOT)/stubdom/libxencall-$(MINIOS_TARGET_ARCH) -whole-archive -lxencall -no-whole-archive
 APP_LDLIBS += -L$(XEN_ROOT)/stubdom/libxc-$(MINIOS_TARGET_ARCH) -whole-archive -lxenguest -lxenctrl -no-whole-archive
 endif
 APP_LDLIBS += -lpci
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH MINI-OS v2 5/5] mini-os: Include libxenforeignmemory with libxc
  2015-07-15 15:46 [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries Ian Campbell
                   ` (23 preceding siblings ...)
  2015-07-15 15:48 ` [PATCH MINI-OS v2 4/5] mini-os: Include libxencall " Ian Campbell
@ 2015-07-15 15:48 ` Ian Campbell
  2015-07-15 15:53 ` [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries Andrew Cooper
                   ` (2 subsequent siblings)
  27 siblings, 0 replies; 55+ messages in thread
From: Ian Campbell @ 2015-07-15 15:48 UTC (permalink / raw)
  To: ian.jackson, wei.liu2, xen-devel
  Cc: minios-devel, roger.pau, Ian Campbell, stefano.stabellini

libxenforeignmemory has just been split out from libxc. From mini-os's
point of view we don't care about the distinction, so keep things
simple by just including libxenforeignmemory if libxc is enabled.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
---
 Makefile | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Makefile b/Makefile
index 835c47b..f4e10c0 100644
--- a/Makefile
+++ b/Makefile
@@ -169,6 +169,7 @@ APP_LDLIBS += -L$(XEN_ROOT)/stubdom/libxentoollog-$(MINIOS_TARGET_ARCH) -whole-a
 APP_LDLIBS += -L$(XEN_ROOT)/stubdom/libxenevtchn-$(MINIOS_TARGET_ARCH) -whole-archive -lxenevtchn -no-whole-archive
 APP_LDLIBS += -L$(XEN_ROOT)/stubdom/libxengnttab-$(MINIOS_TARGET_ARCH) -whole-archive -lxengnttab -no-whole-archive
 APP_LDLIBS += -L$(XEN_ROOT)/stubdom/libxencall-$(MINIOS_TARGET_ARCH) -whole-archive -lxencall -no-whole-archive
+APP_LDLIBS += -L$(XEN_ROOT)/stubdom/libxenforeignmemory-$(MINIOS_TARGET_ARCH) -whole-archive -lxenforeignmemory -no-whole-archive
 APP_LDLIBS += -L$(XEN_ROOT)/stubdom/libxc-$(MINIOS_TARGET_ARCH) -whole-archive -lxenguest -lxenctrl -no-whole-archive
 endif
 APP_LDLIBS += -lpci
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* Re: [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries
  2015-07-15 15:46 [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries Ian Campbell
                   ` (24 preceding siblings ...)
  2015-07-15 15:48 ` [PATCH MINI-OS v2 5/5] mini-os: Include libxenforeignmemory " Ian Campbell
@ 2015-07-15 15:53 ` Andrew Cooper
  2015-07-22 11:12   ` Ian Campbell
  2015-09-22 15:03 ` Oldest supported Xen version in upstream QEMU (Was: Re: [Minios-devel] [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries) Ian Campbell
  2015-09-24 16:47 ` [Minios-devel] [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries Ian Campbell
  27 siblings, 1 reply; 55+ messages in thread
From: Andrew Cooper @ 2015-07-15 15:53 UTC (permalink / raw)
  To: Ian Campbell, xen-devel
  Cc: minios-devel, Ian Jackson, Roger Pau Monne, Wei Liu, Stefano Stabellini

On 15/07/15 16:46, Ian Campbell wrote:
> (this is clearly not 4.6 material, aiming for 4.7)
>
> In <1431963008.4944.80.camel@citrix.com> I proposed stabilising some
> parts of the libxenctrl API/ABI by disaggregating into separate
> libraries.
>
> After the previous proof of concept I have now split out:
>       * xentoollog
>       * evtch
>       * gntdev and gntshr
>       * hypercalls
>       * privileged foreign memory mappings
>
> These represent the core low level functionality which everything else
> needs, I think, and so are moving things down into a layer below libxc
> (i.e. libxc uses all of these).
>
> There are 3 series, against xen.git (15 patches), mini-os.git (5
> patches) and qemu-xen-trad.git (5 patches). The patches against xen.git
> point to the patches in the other two trees via instructions to update
> the relevant Config.mk field. The perils of changing unstable
> interfaces!
>
> NB: minios-devel will only get the mini-os side.
>
> The code in for all three can be found in:
> git://xenbits.xen.org/people/ianc/xen.git               libxenctrl-split-v2
> git://xenbits.xen.org/people/ianc/qemu-xen-unstable.git libxenctrl-split-v2
> git://xenbits.xen.org/people/ianc/mini-os.git           libxenctrl-split-v2
>
> The tip of the xen.git branch contains an extra patch adding a .config
> into the tree which should get the correct things for the HEAD of the
> branch, but not further back.
>
> Still to come would be libraries for specific out of tree purposes
> (device model, kexec), which would be adding new library at the same
> level as libxc I think, rather than underneath, i.e. also using the
> libraries split out here, but hopefully not libxenctrl itself.
>
> The new libraries use linker version-scripts to hopefully make future
> ABI changes be possible in a compatible way.
>
> I'm stilling mulling over putting everything into tools/libs/FOO
> instead of tools/libxenFOO

On balance, +1.  tools/ is already quite a mixed bag of stuff.

> , I still haven't but I could if people think
> it is worthwhile. Eventually I'd like to split libxc into libxenguest
> and libxenctrl to cut down on the amount of strange cross talk...

Very much +1.

FWIW, also splitting xl and libxl into different directories.

~Andrew

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH XEN v2 12/15] tools: Remove xc_map_foreign_batch
  2015-07-15 15:47 ` [PATCH XEN v2 12/15] tools: Remove xc_map_foreign_batch Ian Campbell
@ 2015-07-15 16:08   ` George Dunlap
  0 siblings, 0 replies; 55+ messages in thread
From: George Dunlap @ 2015-07-15 16:08 UTC (permalink / raw)
  To: Ian Campbell, ian.jackson, wei.liu2, xen-devel
  Cc: roger.pau, stefano.stabellini

On 07/15/2015 04:47 PM, Ian Campbell wrote:
> It can trivially be replaced by xc_map_foreign_bulk which is the
> interface I want to move to going forward. All in tree users are
> trivially converted by supplying the appropriate error array and
> adjusting the what error handling exists (which in many cases is not
> much).
> 
> This reduces the twist maze of xc_map_foreign_* by one, which will be
> useful when trying to come up with an underlying stable interface.
> 
> NetBSD and Solaris implemented xc_map_foreign_bulk in terms of
> xc_map_foreign_batch via a compat layer, so xc_map_foreign_batch
> becomes an internal osdep for them. New OS ports should always
> implement xc_map_foreign_bulk instead.
> 
> Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
> Cc: George Dunlap <george.dunlap@eu.citrix.com>

xentrace and xenbaked:

Acked-by: George Dunlap <george.dunlap@citrix.com>

(Note that I'm going to be switching to using @citrix.com in tags post-4.6)

> ---
>  docs/misc/toolstack-library-abis.pandoc | 17 +++-------
>  tools/libxc/include/xenctrl.h           | 10 ------
>  tools/libxc/xc_foreign_memory.c         |  4 ++-
>  tools/libxc/xc_linux_osdep.c            | 59 ++-------------------------------
>  tools/libxc/xc_minios.c                 | 22 ------------
>  tools/libxc/xc_netbsd.c                 | 10 +++---
>  tools/libxc/xc_solaris.c                |  6 ++--
>  tools/libxc/xc_vm_event.c               | 25 ++++++++++----
>  tools/xenmon/xenbaked.c                 | 19 ++++++++---
>  tools/xenpaging/pagein.c                |  4 ++-
>  tools/xenpaging/xenpaging.c             | 12 ++++---
>  tools/xentrace/xentrace.c               | 10 +++---
>  12 files changed, 68 insertions(+), 130 deletions(-)
> 
> diff --git a/docs/misc/toolstack-library-abis.pandoc b/docs/misc/toolstack-library-abis.pandoc
> index 271e4b5..4ad6c7d 100644
> --- a/docs/misc/toolstack-library-abis.pandoc
> +++ b/docs/misc/toolstack-library-abis.pandoc
> @@ -274,7 +274,6 @@ Interface                         Underlying interface           Known external
>  `xc_map_foreign_pages`            `IOCTL_PRIVCMD_MMAP...`        qemu-pv
>  `xc_map_foreign_range`            `IOCTL_PRIVCMD_MMAP...`        qemu-dm, and qemu-pv
>  `xc_map_foreign_ranges`
> -`xc_map_foreign_batch`
>  `xc_map_foreign_bulk`             `IOCTL_PRIVCMD_MMAPBATCH_V2`   qemu-dm
>  
>  ### Managing guest memory map
> @@ -883,7 +882,6 @@ osdep level interfaces:
>  
>  Interface            Linux Minios Netbsd Freebsd Solaris
>  -------------------- ----- ------ ------ ------- -------
> -`map_foreign_batch`  Y     Y      Y              Y
>  `map_foreign_bulk`   Y     Y      compat Y       compat
>  `map_foreign_range`  Y     Y      Y      Y       Y
>  `map_foreign_ranges` Y     Y      Y      Y       Y
> @@ -897,7 +895,6 @@ Some osdep call other `xc_map_foreign_*` recursivley:
>  
>  Interface            Linux                        FreeBSD
>  -------------------- ---------------------------- -------------------------
> -`map_foreign_batch`  `IOCTL_PRIVCMD_MMAPBATCH`    N/A
>  `map_foreign_bulk`   `IOCTL_PRIVCMD_MMAPBATCH_V2` `IOCTL_PRIVCMD_MMAPBATCH`
>  `map_foreign_range`  `xc_map_foreign_pages`       `xc_map_foreign_pages`
>  `map_foreign_ranges` `xc_map_foreign_pages`       `xc_map_foreign_pages`
> @@ -909,17 +906,14 @@ Interface               Underlying interface
>  `xc_map_foreign_pages`  `xc_map_foreign_bulk`
>  `xc_map_foreign_range`  `osdep: map_foreign_range`
>  `xc_map_foreign_ranges` `osdep: map_foreign_ranges`
> -`xc_map_foreign_batch`  `osdep: map_foreign_batch`
>  `xc_map_foreign_bulk`   `osdep: map_foreign_bulk`
>  
>  `osdep: *` have been collapsed since osdep layer was removed.
>  
> -`xc_map_foreign_bulk_compat` is an internal helper used by osdep
> -backends which have not implemented there own version. It uses
> -`xc_map_foreign_batch`.
> -
> -`xc_map_foreign_batch_single` is part of linux osdep, but name has
> -leaked.
> +`xc_map_foreign_bulk` can be an internal compat helper used by oses
> +which have not implemented their own version. It used to use
> +`xc_map_foreign_batch` which is now an osdep for those OSes which need
> +it.
>  
>  Interface               Internal users               External users
>  ----------------------  --------------               --------------
> @@ -928,11 +922,10 @@ Interface               Internal users               External users
>                          mfndump, memshrtool, xenmon,
>                          xenstored, xentrace
>  `xc_map_foreign_ranges` NONE
> -`xc_map_foreign_batch`  xenmon, xenpaging, xentrace
>  `xc_map_foreign_bulk`   used recursively             qemu-dm
>  
>  Only one interface should become a stable API. Something based on
>  `xc_map_foreign_bulk` seems most appropriate (it is used by
>  `xc_map_foreign_pages` as well as by xc_map_foreign_range` and
>  `xc_map_foreign_ranges` on Linux + FreeBSD. A compat version exists in
> -terms for `xc_map_foreign_batch` for other OSes.
> +terms of `xc_map_foreign_batch` for other OSes.
> diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h
> index 61f68bb..201fd70 100644
> --- a/tools/libxc/include/xenctrl.h
> +++ b/tools/libxc/include/xenctrl.h
> @@ -1367,16 +1367,6 @@ void *xc_map_foreign_pages(xc_interface *xch, uint32_t dom, int prot,
>                             const xen_pfn_t *arr, int num );
>  
>  /**
> - * DEPRECATED - use xc_map_foreign_bulk() instead.
> - *
> - * Like xc_map_foreign_pages(), except it can succeeed partially.
> - * When a page cannot be mapped, its PFN in @arr is or'ed with
> - * 0xF0000000 to indicate the error.
> - */
> -void *xc_map_foreign_batch(xc_interface *xch, uint32_t dom, int prot,
> -                           xen_pfn_t *arr, int num );
> -
> -/**
>   * Like xc_map_foreign_pages(), except it can succeed partially.
>   * When a page cannot be mapped, its respective field in @err is
>   * set to the corresponding errno value.
> diff --git a/tools/libxc/xc_foreign_memory.c b/tools/libxc/xc_foreign_memory.c
> index da77e9d..ae133a1 100644
> --- a/tools/libxc/xc_foreign_memory.c
> +++ b/tools/libxc/xc_foreign_memory.c
> @@ -56,6 +56,8 @@ void *xc_map_foreign_pages(xc_interface *xch, uint32_t dom, int prot,
>   * just implement xc_map_foreign_bulk.
>   */
>  #if defined(__NetBSD__) || defined(__sun__)
> +void *osdep_map_foreign_batch(xc_interface *xch, uint32_t dom, int prot,
> +                              xen_pfn_t *arr, int num );
>  void *xc_map_foreign_bulk(xc_interface *xch,
>                            uint32_t dom, int prot,
>                            const xen_pfn_t *arr, int *err, unsigned int num)
> @@ -76,7 +78,7 @@ void *xc_map_foreign_bulk(xc_interface *xch,
>      }
>  
>      memcpy(pfn, arr, num * sizeof(*arr));
> -    ret = xc_map_foreign_batch(xch, dom, prot, pfn, num);
> +    ret = osdep_map_foreign_batch(xch, dom, prot, pfn, num);
>  
>      if (ret) {
>          for (i = 0; i < num; ++i)
> diff --git a/tools/libxc/xc_linux_osdep.c b/tools/libxc/xc_linux_osdep.c
> index 488e8df..6641bd1 100644
> --- a/tools/libxc/xc_linux_osdep.c
> +++ b/tools/libxc/xc_linux_osdep.c
> @@ -86,8 +86,8 @@ int osdep_privcmd_close(xc_interface *xch)
>      return close(fd);
>  }
>  
> -static int xc_map_foreign_batch_single(int fd, uint32_t dom,
> -                                       xen_pfn_t *mfn, unsigned long addr)
> +static int map_foreign_batch_single(int fd, uint32_t dom,
> +                                    xen_pfn_t *mfn, unsigned long addr)
>  {
>      privcmd_mmapbatch_t ioctlx;
>      int rc;
> @@ -108,59 +108,6 @@ static int xc_map_foreign_batch_single(int fd, uint32_t dom,
>      return rc;
>  }
>  
> -void *xc_map_foreign_batch(xc_interface *xch,
> -                           uint32_t dom, int prot,
> -                           xen_pfn_t *arr, int num)
> -{
> -    int fd = xch->privcmdfd;
> -    privcmd_mmapbatch_t ioctlx;
> -    void *addr;
> -    int rc;
> -
> -    addr = mmap(NULL, num << XC_PAGE_SHIFT, prot, MAP_SHARED, fd, 0);
> -    if ( addr == MAP_FAILED )
> -    {
> -        PERROR("xc_map_foreign_batch: mmap failed");
> -        return NULL;
> -    }
> -
> -    ioctlx.num = num;
> -    ioctlx.dom = dom;
> -    ioctlx.addr = (unsigned long)addr;
> -    ioctlx.arr = arr;
> -
> -    rc = ioctl(fd, IOCTL_PRIVCMD_MMAPBATCH, &ioctlx);
> -    if ( (rc < 0) && (errno == ENOENT) )
> -    {
> -        int i;
> -
> -        for ( i = 0; i < num; i++ )
> -        {
> -            if ( (arr[i] & PRIVCMD_MMAPBATCH_MFN_ERROR) ==
> -                           PRIVCMD_MMAPBATCH_PAGED_ERROR )
> -            {
> -                unsigned long paged_addr = (unsigned long)addr + (i << XC_PAGE_SHIFT);
> -                rc = xc_map_foreign_batch_single(fd, dom, &arr[i],
> -                                                 paged_addr);
> -                if ( rc < 0 )
> -                    goto out;
> -            }
> -        }
> -    }
> -
> - out:
> -    if ( rc < 0 )
> -    {
> -        int saved_errno = errno;
> -        PERROR("xc_map_foreign_batch: ioctl failed");
> -        (void)munmap(addr, num << XC_PAGE_SHIFT);
> -        errno = saved_errno;
> -        return NULL;
> -    }
> -
> -    return addr;
> -}
> -
>  /*
>   * Retry mmap of all paged gfns in batches
>   * retuns < 0 on fatal error
> @@ -300,7 +247,7 @@ void *xc_map_foreign_bulk(xc_interface *xch,
>                      err[i] = rc ?: -EINVAL;
>                      continue;
>                  }
> -                rc = xc_map_foreign_batch_single(fd, dom, pfn + i,
> +                rc = map_foreign_batch_single(fd, dom, pfn + i,
>                          (unsigned long)addr + ((unsigned long)i<<XC_PAGE_SHIFT));
>                  if ( rc < 0 )
>                  {
> diff --git a/tools/libxc/xc_minios.c b/tools/libxc/xc_minios.c
> index 27a4c4a..ed20652 100644
> --- a/tools/libxc/xc_minios.c
> +++ b/tools/libxc/xc_minios.c
> @@ -74,28 +74,6 @@ void *xc_map_foreign_bulk(xc_interface *xch,
>      return map_frames_ex(arr, num, 1, 0, 1, dom, err, pt_prot);
>  }
>  
> -void *xc_map_foreign_batch(xc_interface *xch,
> -                           uint32_t dom, int prot,
> -                           xen_pfn_t *arr, int num)
> -{
> -    unsigned long pt_prot = 0;
> -    int err[num];
> -    int i;
> -    unsigned long addr;
> -
> -    if (prot & PROT_READ)
> -	pt_prot = L1_PROT_RO;
> -    if (prot & PROT_WRITE)
> -	pt_prot = L1_PROT;
> -
> -    addr = (unsigned long) map_frames_ex(arr, num, 1, 0, 1, dom, err, pt_prot);
> -    for (i = 0; i < num; i++) {
> -        if (err[i])
> -            arr[i] |= 0xF0000000;
> -    }
> -    return (void *) addr;
> -}
> -
>  void *xc_map_foreign_range(xc_interface *xch,
>                             uint32_t dom,
>                             int size, int prot,
> diff --git a/tools/libxc/xc_netbsd.c b/tools/libxc/xc_netbsd.c
> index a61e52f..f02015c 100644
> --- a/tools/libxc/xc_netbsd.c
> +++ b/tools/libxc/xc_netbsd.c
> @@ -68,16 +68,16 @@ int osdep_privcmd_close(xc_interface *xch)
>      return close(fd);
>  }
>  
> -void *xc_map_foreign_batch(xc_interface *xch,
> -                           uint32_t dom, int prot,
> -                           xen_pfn_t *arr, int num)
> +void *osdep_map_foreign_batch(xc_interface *xch,
> +                              uint32_t dom, int prot,
> +                              xen_pfn_t *arr, int num)
>  {
>      int fd = xch->privcmdfd;
>      privcmd_mmapbatch_t ioctlx;
>      void *addr;
>      addr = mmap(NULL, num*XC_PAGE_SIZE, prot, MAP_ANON | MAP_SHARED, -1, 0);
>      if ( addr == MAP_FAILED ) {
> -        PERROR("xc_map_foreign_batch: mmap failed");
> +        PERROR("osdep_map_foreign_batch: mmap failed");
>          return NULL;
>      }
>  
> @@ -88,7 +88,7 @@ void *xc_map_foreign_batch(xc_interface *xch,
>      if ( ioctl(fd, IOCTL_PRIVCMD_MMAPBATCH, &ioctlx) < 0 )
>      {
>          int saved_errno = errno;
> -        PERROR("xc_map_foreign_batch: ioctl failed");
> +        PERROR("osdep_map_foreign_batch: ioctl failed");
>          (void)munmap(addr, num*XC_PAGE_SIZE);
>          errno = saved_errno;
>          return NULL;
> diff --git a/tools/libxc/xc_solaris.c b/tools/libxc/xc_solaris.c
> index 1e1a0c4..0a0fd14 100644
> --- a/tools/libxc/xc_solaris.c
> +++ b/tools/libxc/xc_solaris.c
> @@ -68,9 +68,9 @@ int osdep_privcmd_close(xc_interface *xch)
>      return close(fd);
>  }
>  
> -void *xc_map_foreign_batch(xc_interface *xch,
> -                          uint32_t dom, int prot,
> -                          xen_pfn_t *arr, int num)
> +void *osdep_map_foreign_batch(xc_interface *xch,
> +                              uint32_t dom, int prot,
> +                              xen_pfn_t *arr, int num)
>  {
>      int fd = xch->privcmdfd;
>      privcmd_mmapbatch_t ioctlx;
> diff --git a/tools/libxc/xc_vm_event.c b/tools/libxc/xc_vm_event.c
> index a5b3277..4d7e7cc 100644
> --- a/tools/libxc/xc_vm_event.c
> +++ b/tools/libxc/xc_vm_event.c
> @@ -46,6 +46,7 @@ void *xc_vm_event_enable(xc_interface *xch, domid_t domain_id, int param,
>      void *ring_page = NULL;
>      uint64_t pfn;
>      xen_pfn_t ring_pfn, mmap_pfn;
> +    int err;
>      unsigned int op, mode;
>      int rc1, rc2, saved_errno;
>  
> @@ -73,9 +74,9 @@ void *xc_vm_event_enable(xc_interface *xch, domid_t domain_id, int param,
>  
>      ring_pfn = pfn;
>      mmap_pfn = pfn;
> -    ring_page = xc_map_foreign_batch(xch, domain_id, PROT_READ | PROT_WRITE,
> -                                     &mmap_pfn, 1);
> -    if ( mmap_pfn & XEN_DOMCTL_PFINFO_XTAB )
> +    ring_page = xc_map_foreign_bulk(xch, domain_id, PROT_READ | PROT_WRITE,
> +				    &mmap_pfn, &err, 1);
> +    if ( !ring_page )
>      {
>          /* Map failed, populate ring page */
>          rc1 = xc_domain_populate_physmap_exact(xch, domain_id, 1, 0, 0,
> @@ -87,11 +88,11 @@ void *xc_vm_event_enable(xc_interface *xch, domid_t domain_id, int param,
>          }
>  
>          mmap_pfn = ring_pfn;
> -        ring_page = xc_map_foreign_batch(xch, domain_id, PROT_READ | PROT_WRITE,
> -                                         &mmap_pfn, 1);
> -        if ( mmap_pfn & XEN_DOMCTL_PFINFO_XTAB )
> +        ring_page = xc_map_foreign_bulk(xch, domain_id, PROT_READ | PROT_WRITE,
> +					&mmap_pfn, &err, 1);
> +        if ( !ring_page )
>          {
> -            PERROR("Could not map the ring page\n");
> +            PERROR("Could not map the ring page: %d\n", err);
>              goto out;
>          }
>      }
> @@ -157,3 +158,13 @@ void *xc_vm_event_enable(xc_interface *xch, domid_t domain_id, int param,
>  
>      return ring_page;
>  }
> +
> +/*
> + * Local variables:
> + * mode: C
> + * c-file-style: "BSD"
> + * c-basic-offset: 4
> + * tab-width: 4
> + * indent-tabs-mode: nil
> + * End:
> + */
> diff --git a/tools/xenmon/xenbaked.c b/tools/xenmon/xenbaked.c
> index f092aec..9e2a49b 100644
> --- a/tools/xenmon/xenbaked.c
> +++ b/tools/xenmon/xenbaked.c
> @@ -408,14 +408,15 @@ static struct t_struct *map_tbufs(unsigned long tbufs_mfn, unsigned int num,
>                                     + tbufs.t_info->mfn_offset[i];
>          int j;
>          xen_pfn_t pfn_list[tbufs.t_info->tbuf_size];
> +        int err_list[tbufs.t_info->tbuf_size];
>  
>          for ( j=0; j<tbufs.t_info->tbuf_size; j++)
>              pfn_list[j] = (xen_pfn_t)mfn_list[j];
>  
> -        tbufs.meta[i] = xc_map_foreign_batch(xc_handle, DOMID_XEN,
> -                                             PROT_READ | PROT_WRITE,
> -                                             pfn_list,
> -                                             tbufs.t_info->tbuf_size);
> +        tbufs.meta[i] = xc_map_foreign_bulk(xc_handle, DOMID_XEN,
> +					    PROT_READ | PROT_WRITE,
> +					    pfn_list, err_list,
> +					    tbufs.t_info->tbuf_size);
>          if ( tbufs.meta[i] == NULL )
>          {
>              PERROR("Failed to map cpu buffer!");
> @@ -1176,3 +1177,13 @@ static int process_record(int cpu, struct t_rec *r)
>  
>      return 4 + (r->cycles_included ? 8 : 0) + (r->extra_u32 * 4);
>  }
> +
> +/*
> + * Local variables:
> + * mode: C
> + * c-file-style: "BSD"
> + * c-basic-offset: 4
> + * tab-width: 4
> + * indent-tabs-mode: nil
> + * End:
> + */
> diff --git a/tools/xenpaging/pagein.c b/tools/xenpaging/pagein.c
> index 7cb0f33..18699ec 100644
> --- a/tools/xenpaging/pagein.c
> +++ b/tools/xenpaging/pagein.c
> @@ -23,6 +23,7 @@ static void *page_in(void *arg)
>      void *page;
>      int i, num;
>      xen_pfn_t gfns[XENPAGING_PAGEIN_QUEUE_SIZE];
> +    int errs[XENPAGING_PAGEIN_QUEUE_SIZE];
>  
>      while (1)
>      {
> @@ -42,7 +43,8 @@ static void *page_in(void *arg)
>          pthread_mutex_unlock(&page_in_mutex);
>  
>          /* Ignore errors */
> -        page = xc_map_foreign_pages(pia->xch, pia->dom, PROT_READ, gfns, num);
> +        page = xc_map_foreign_bulk(pia->xch, pia->dom, PROT_READ,
> +                                   gfns, errs, num);
>          if (page)
>              munmap(page, PAGE_SIZE * num);
>      }
> diff --git a/tools/xenpaging/xenpaging.c b/tools/xenpaging/xenpaging.c
> index 6776896..a819a5b 100644
> --- a/tools/xenpaging/xenpaging.c
> +++ b/tools/xenpaging/xenpaging.c
> @@ -282,6 +282,7 @@ static struct xenpaging *xenpaging_init(int argc, char *argv[])
>      char *p;
>      int rc;
>      unsigned long ring_pfn, mmap_pfn;
> +    int mmap_err;
>  
>      /* Allocate memory */
>      paging = calloc(1, sizeof(struct xenpaging));
> @@ -343,8 +344,8 @@ static struct xenpaging *xenpaging_init(int argc, char *argv[])
>                          HVM_PARAM_PAGING_RING_PFN, &ring_pfn);
>      mmap_pfn = ring_pfn;
>      paging->vm_event.ring_page = 
> -        xc_map_foreign_batch(xch, paging->vm_event.domain_id, 
> -                                PROT_READ | PROT_WRITE, &mmap_pfn, 1);
> +        xc_map_foreign_bulk(xch, paging->vm_event.domain_id,
> +                            PROT_READ | PROT_WRITE, &mmap_pfn, &mmap_err, 1);
>      if ( mmap_pfn & XEN_DOMCTL_PFINFO_XTAB )
>      {
>          /* Map failed, populate ring page */
> @@ -359,11 +360,12 @@ static struct xenpaging *xenpaging_init(int argc, char *argv[])
>  
>          mmap_pfn = ring_pfn;
>          paging->vm_event.ring_page = 
> -            xc_map_foreign_batch(xch, paging->vm_event.domain_id, 
> -                                    PROT_READ | PROT_WRITE, &mmap_pfn, 1);
> +            xc_map_foreign_bulk(xch, paging->vm_event.domain_id,
> +                                PROT_READ | PROT_WRITE,
> +                                &mmap_pfn, &mmap_err, 1);
>          if ( mmap_pfn & XEN_DOMCTL_PFINFO_XTAB )
>          {
> -            PERROR("Could not map the ring page\n");
> +            PERROR("Could not map the ring page: %d\n", mmap_err);
>              goto err;
>          }
>      }
> diff --git a/tools/xentrace/xentrace.c b/tools/xentrace/xentrace.c
> index c970d42..f66a77c 100644
> --- a/tools/xentrace/xentrace.c
> +++ b/tools/xentrace/xentrace.c
> @@ -504,14 +504,15 @@ static struct t_struct *map_tbufs(unsigned long tbufs_mfn, unsigned int num,
>                                     + tbufs.t_info->mfn_offset[i];
>          int j;
>          xen_pfn_t pfn_list[tbufs.t_info->tbuf_size];
> +        int pfn_err[tbufs.t_info->tbuf_size];
>  
>          for ( j=0; j<tbufs.t_info->tbuf_size; j++)
>              pfn_list[j] = (xen_pfn_t)mfn_list[j];
>  
> -        tbufs.meta[i] = xc_map_foreign_batch(xc_handle, DOMID_XEN,
> -                                             PROT_READ | PROT_WRITE,
> -                                             pfn_list,
> -                                             tbufs.t_info->tbuf_size);
> +        tbufs.meta[i] = xc_map_foreign_bulk(xc_handle, DOMID_XEN,
> +                                            PROT_READ | PROT_WRITE,
> +                                            pfn_list, pfn_err,
> +                                            tbufs.t_info->tbuf_size);
>          if ( tbufs.meta[i] == NULL )
>          {
>              PERROR("Failed to map cpu buffer!");
> @@ -1221,6 +1222,7 @@ int main(int argc, char **argv)
>  
>      return ret;
>  }
> +
>  /*
>   * Local variables:
>   * mode: C
> 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH XEN v2 09/15] tools/libxc: Remove osdep indirection for privcmd
       [not found]   ` <01C96D24-A13F-46A6-A8A9-5C04E2E199AF@citrix.com>
@ 2015-07-16  7:59     ` Dave Scott
  2015-07-16  8:35       ` Ian Campbell
  0 siblings, 1 reply; 55+ messages in thread
From: Dave Scott @ 2015-07-16  7:59 UTC (permalink / raw)
  To: Ian Campbell, Ian Jackson, Wei Liu, <xen-devel@lists.xen.org>
  Cc: Stefano Stabellini, Roger Pau Monne


> On 16 Jul 2015, at 05:57, David Scott (Sales UK) <david.scott@citrix.com> wrote:
> 
> One for you I think Dave?
> 
> Sent from my iPhone
> 
> Begin forwarded message:
> 
>> From: "Ian Campbell" <ian.campbell@citrix.com>
>> To: "Ian Jackson" <Ian.Jackson@citrix.com>, "Wei Liu" <wei.liu2@citrix.com>, "xen-devel@lists.xen.org" <xen-devel@lists.xen.org>
>> Cc: "Stefano Stabellini" <Stefano.Stabellini@citrix.com>, "Roger Pau Monne" <roger.pau@citrix.com>, "Ian Campbell" <Ian.Campbell@citrix.com>, "David Scott (Sales UK)" <david.scott@citrix.com>
>> Subject: [PATCH XEN v2 09/15] tools/libxc: Remove osdep indirection for privcmd
>> 
>> The alternative backend (a xen-api/xapi shim) is no longer around and
>> so this stuff is now just baggage which is getting in the way of
>> refactoring libxenctrl.

Yes, we no longer use the fake libxenctrl (“xiu”) stuff.

>> 
>> Nested virt probably suffices for this use case now.
>> 
>> This was the last component of the osdep infrastructure, so all the
>> dynamic loading etc stuff all falls away too.
>> 
>> As part of this I was forced to investigate the twisty
>> xc_map_foreign_* maze, which I have added to the
>> toolstack-library-apis doc in the hopes of doing something sensible.
>> 
>> NetBSD and Solaris now call xc_map_foreign_bulk_compat directly from
>> their xc_map_foreign_bulk, which could have been achieved by using
>> some ifdefs around a renamed function. This will fall out in the wash
>> when these functions move to their own library.
>> 
>> Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
>> Cc: David Scott <david.scott@citrix.com>

Confusingly my email is <dave.scott@citrix.com> (‘dave’ rather than ‘david’) — best to avoid cc:ing ‘david.scott’ as he probably hasn’t got xen-devel email filters set up ;-)

>> ---
>> config/FreeBSD.mk                       |   2 -
>> config/NetBSD.mk                        |   3 -
>> config/NetBSDRump.mk                    |   1 -
>> config/StdGNU.mk                        |   1 -
>> config/SunOS.mk                         |   1 -
>> docs/misc/toolstack-library-abis.pandoc |  64 +++++++++++-
>> tools/libxc/Makefile                    |  27 ++---
>> tools/libxc/include/xenctrl.h           |   9 --
>> tools/libxc/include/xenctrlosdep.h      | 134 ------------------------
>> tools/libxc/xc_foreign_memory.c         |  31 +-----
>> tools/libxc/xc_freebsd_osdep.c          | 100 +++++-------------
>> tools/libxc/xc_hcall_buf.c              |   6 +-
>> tools/libxc/xc_linux_osdep.c            |  88 +++++-----------
>> tools/libxc/xc_minios.c                 |  82 +++++----------
>> tools/libxc/xc_netbsd.c                 |  90 ++++++-----------
>> tools/libxc/xc_private.c                | 174 ++------------------------------
>> tools/libxc/xc_private.h                |  19 ++--
>> tools/libxc/xc_solaris.c                |  90 ++++++-----------
>> tools/libxc/xenctrl_osdep_ENOSYS.c      | 123 ----------------------
>> tools/ocaml/libs/xc/xenctrl.ml          |   2 -
>> tools/ocaml/libs/xc/xenctrl.mli         |   1 -
>> tools/ocaml/libs/xc/xenctrl_stubs.c     |   7 --
>> tools/ocaml/xenstored/domains.ml        |   6 +-
>> tools/ocaml/xenstored/xenstored.ml      |   5 +-

These are fine,

Acked-by: David Scott <dave.scott@citrix.com>

Thanks,
Dave

>> 24 files changed, 240 insertions(+), 826 deletions(-)
>> delete mode 100644 tools/libxc/include/xenctrlosdep.h
>> delete mode 100644 tools/libxc/xenctrl_osdep_ENOSYS.c
>> 
>> diff --git a/config/FreeBSD.mk b/config/FreeBSD.mk
>> index 5a13d607..bb3a5d0 100644
>> --- a/config/FreeBSD.mk
>> +++ b/config/FreeBSD.mk
>> @@ -1,6 +1,4 @@
>> include $(XEN_ROOT)/config/StdGNU.mk
>> 
>> -DLOPEN_LIBS =
>> -
>> # No wget on FreeBSD base system
>> WGET = ftp
>> diff --git a/config/NetBSD.mk b/config/NetBSD.mk
>> index 21318d6..cf766e5 100644
>> --- a/config/NetBSD.mk
>> +++ b/config/NetBSD.mk
>> @@ -1,6 +1,3 @@
>> include $(XEN_ROOT)/config/StdGNU.mk
>> 
>> -# Override settings for this OS
>> -DLOPEN_LIBS =
>> -
>> WGET = ftp
>> diff --git a/config/NetBSDRump.mk b/config/NetBSDRump.mk
>> index 2a87218..74755a1 100644
>> --- a/config/NetBSDRump.mk
>> +++ b/config/NetBSDRump.mk
>> @@ -1,6 +1,5 @@
>> include $(XEN_ROOT)/config/StdGNU.mk
>> 
>> -DLOPEN_LIBS =
>> PTHREAD_LIBS =
>> 
>> WGET = ftp
>> diff --git a/config/StdGNU.mk b/config/StdGNU.mk
>> index 129d5c8..39d36b2 100644
>> --- a/config/StdGNU.mk
>> +++ b/config/StdGNU.mk
>> @@ -31,7 +31,6 @@ DEBUG_DIR ?= /usr/lib/debug
>> 
>> SOCKET_LIBS =
>> UTIL_LIBS = -lutil
>> -DLOPEN_LIBS = -ldl
>> 
>> SONAME_LDFLAG = -soname
>> SHLIB_LDFLAGS = -shared
>> diff --git a/config/SunOS.mk b/config/SunOS.mk
>> index db5e898..86a384d 100644
>> --- a/config/SunOS.mk
>> +++ b/config/SunOS.mk
>> @@ -27,7 +27,6 @@ SunOS_LIBDIR_x86_64 = /usr/sfw/lib/amd64
>> SOCKET_LIBS = -lsocket
>> PTHREAD_LIBS = -lpthread
>> UTIL_LIBS =
>> -DLOPEN_LIBS = -ldl
>> 
>> SONAME_LDFLAG = -h
>> SHLIB_LDFLAGS = -R $(SunOS_LIBDIR) -shared
>> diff --git a/docs/misc/toolstack-library-abis.pandoc b/docs/misc/toolstack-library-abis.pandoc
>> index 6b6146a..d1550a6 100644
>> --- a/docs/misc/toolstack-library-abis.pandoc
>> +++ b/docs/misc/toolstack-library-abis.pandoc
>> @@ -187,7 +187,6 @@ Notes:
>> ### Basic interface
>> 
>>     - xc_interface_close
>> -    - xc_interface_is_fake
>>     - xc_interface_open
>> 
>> ### Event channels
>> @@ -511,7 +510,6 @@ Symbols:
>>     - xc_monitor_write_ctrlreg
>>     - xc_nodemap_alloc
>>     - xc_numainfo
>> -    - xc_osdep_log
>>     - xc_pcitopoinfo
>>     - xc_perfc_query
>>     - xc_perfc_query_number
>> @@ -871,3 +869,65 @@ functionality areas:
>>     - xc_kexec_load
>>     - xc_kexec_unload
>>     - xc_version
>> +
>> +# Foreign memory mapping functions
>> +
>> +The `xc_map_foreign_*` functions are a bit of a twisty maze.
>> +
>> +osdep level interfaces:
>> +
>> +Interface            Linux Minios Netbsd Freebsd Solaris
>> +-------------------- ----- ------ ------ ------- -------
>> +`map_foreign_batch`  Y     Y      Y              Y
>> +`map_foreign_bulk`   Y     Y      compat Y       compat
>> +`map_foreign_range`  Y     Y      Y      Y       Y
>> +`map_foreign_ranges` Y     Y      Y      Y       Y
>> +
>> +_compat_ means using `xc_map_foreign_bulk_compat`
>> +
>> +`xc_map_foreign_pages` is common and implemented using
>> +`xc_map_foreign_bulk`.
>> +
>> +Some osdep call other `xc_map_foreign_*` recursivley:
>> +
>> +Interface            Linux                        FreeBSD
>> +-------------------- ---------------------------- -------------------------
>> +`map_foreign_batch`  `IOCTL_PRIVCMD_MMAPBATCH`    N/A
>> +`map_foreign_bulk`   `IOCTL_PRIVCMD_MMAPBATCH_V2` `IOCTL_PRIVCMD_MMAPBATCH`
>> +`map_foreign_range`  `xc_map_foreign_pages`       `xc_map_foreign_pages`
>> +`map_foreign_ranges` `xc_map_foreign_pages`       `xc_map_foreign_pages`
>> +
>> +libxenctrl level interfaces:
>> +
>> +Interface               Underlying interface
>> +----------------------  ---------------------------
>> +`xc_map_foreign_pages`  `xc_map_foreign_bulk`
>> +`xc_map_foreign_range`  `osdep: map_foreign_range`
>> +`xc_map_foreign_ranges` `osdep: map_foreign_ranges`
>> +`xc_map_foreign_batch`  `osdep: map_foreign_batch`
>> +`xc_map_foreign_bulk`   `osdep: map_foreign_bulk`
>> +
>> +`osdep: *` have been collapsed since osdep layer was removed.
>> +
>> +`xc_map_foreign_bulk_compat` is an internal helper used by osdep
>> +backends which have not implemented there own version. It uses
>> +`xc_map_foreign_batch`.
>> +
>> +`xc_map_foreign_batch_single` is part of linux osdep, but name has
>> +leaked.
>> +
>> +Interface               Internal users               External users
>> +----------------------  --------------               --------------
>> +`xc_map_foreign_pages`  xenpaging                    qemu-pv
>> +`xc_map_foreign_range`  xenconsole, kdd, libxl,      qemu-dm, qemu-pv
>> +                        mfndump, memshrtool, xenmon,
>> +                        xenstored, xentrace
>> +`xc_map_foreign_ranges` NONE
>> +`xc_map_foreign_batch`  xenmon, xenpaging, xentrace
>> +`xc_map_foreign_bulk`   used recursively             qemu-dm
>> +
>> +Only one interface should become a stable API. Something based on
>> +`xc_map_foreign_bulk` seems most appropriate (it is used by
>> +`xc_map_foreign_pages` as well as by xc_map_foreign_range` and
>> +`xc_map_foreign_ranges` on Linux + FreeBSD. A compat version exists in
>> +terms for `xc_map_foreign_batch` for other OSes.
>> diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile
>> index 3c939ce..77d2ae1 100644
>> --- a/tools/libxc/Makefile
>> +++ b/tools/libxc/Makefile
>> @@ -102,8 +102,6 @@ GUEST_SRCS-y                 += xc_dom_decompress_unsafe_lzo1x.c
>> GUEST_SRCS-y                 += xc_dom_decompress_unsafe_xz.c
>> endif
>> 
>> -OSDEP_SRCS-y                 += xenctrl_osdep_ENOSYS.c
>> -
>> -include $(XEN_TARGET_ARCH)/Makefile
>> 
>> CFLAGS   += -Werror -Wmissing-prototypes
>> @@ -122,11 +120,8 @@ CTRL_PIC_OBJS := $(patsubst %.c,%.opic,$(CTRL_SRCS-y))
>> GUEST_LIB_OBJS := $(patsubst %.c,%.o,$(GUEST_SRCS-y))
>> GUEST_PIC_OBJS := $(patsubst %.c,%.opic,$(GUEST_SRCS-y))
>> 
>> -OSDEP_LIB_OBJS := $(patsubst %.c,%.o,$(OSDEP_SRCS-y))
>> -OSDEP_PIC_OBJS := $(patsubst %.c,%.opic,$(OSDEP_SRCS-y))
>> -
>> -$(CTRL_LIB_OBJS) $(GUEST_LIB_OBJS) $(OSDEP_LIB_OBJS) \
>> -$(CTRL_PIC_OBJS) $(GUEST_PIC_OBJS) $(OSDEP_PIC_OBJS) : CFLAGS += -include $(XEN_ROOT)/tools/config.h
>> +$(CTRL_LIB_OBJS) $(GUEST_LIB_OBJS) \
>> +$(CTRL_PIC_OBJS) $(GUEST_PIC_OBJS): CFLAGS += -include $(XEN_ROOT)/tools/config.h
>> 
>> $(CTRL_LIB_OBJS) $(CTRL_PIC_OBJS): CFLAGS += $(CFLAGS_libxengnttab) $(CFLAGS_libxengntshr)
>> 
>> @@ -140,17 +135,13 @@ ifneq ($(nosharedlibs),y)
>> LIB += libxenguest.so libxenguest.so.$(MAJOR) libxenguest.so.$(MAJOR).$(MINOR)
>> endif
>> 
>> -ifneq ($(nosharedlibs),y)
>> -LIB += xenctrl_osdep_ENOSYS.so
>> -endif
>> -
>> genpath-target = $(call buildmakevars2header,_paths.h)
>> $(eval $(genpath-target))
>> 
>> xc_private.h: _paths.h
>> 
>> -$(CTRL_LIB_OBJS) $(GUEST_LIB_OBJS) $(OSDEP_LIB_OBJS) \
>> -$(CTRL_PIC_OBJS) $(GUEST_PIC_OBJS) $(OSDEP_PIC_OBJS): xc_private.h
>> +$(CTRL_LIB_OBJS) $(GUEST_LIB_OBJS) \
>> +$(CTRL_PIC_OBJS) $(GUEST_PIC_OBJS): xc_private.h
>> 
>> .PHONY: all
>> all: build
>> @@ -170,7 +161,7 @@ install: build
>>    $(INSTALL_DATA) libxenctrl.a $(DESTDIR)$(libdir)
>>    $(SYMLINK_SHLIB) libxenctrl.so.$(MAJOR).$(MINOR) $(DESTDIR)$(libdir)/libxenctrl.so.$(MAJOR)
>>    $(SYMLINK_SHLIB) libxenctrl.so.$(MAJOR) $(DESTDIR)$(libdir)/libxenctrl.so
>> -    $(INSTALL_DATA) include/xenctrl.h include/xenctrl_compat.h include/xenctrlosdep.h $(DESTDIR)$(includedir)
>> +    $(INSTALL_DATA) include/xenctrl.h include/xenctrl_compat.h $(DESTDIR)$(includedir)
>>    $(INSTALL_SHLIB) libxenguest.so.$(MAJOR).$(MINOR) $(DESTDIR)$(libdir)
>>    $(INSTALL_DATA) libxenguest.a $(DESTDIR)$(libdir)
>>    $(SYMLINK_SHLIB) libxenguest.so.$(MAJOR).$(MINOR) $(DESTDIR)$(libdir)/libxenguest.so.$(MAJOR)
>> @@ -186,8 +177,7 @@ clean:
>>    rm -rf *.rpm $(LIB) *~ $(DEPS) \
>>             _paths.h \
>>             $(CTRL_LIB_OBJS) $(CTRL_PIC_OBJS) \
>> -            $(GUEST_LIB_OBJS) $(GUEST_PIC_OBJS) \
>> -            $(OSDEP_LIB_OBJS) $(OSDEP_PIC_OBJS)
>> +            $(GUEST_LIB_OBJS) $(GUEST_PIC_OBJS)
>> 
>> .PHONY: distclean
>> distclean: clean
>> @@ -213,7 +203,7 @@ libxenctrl.so.$(MAJOR): libxenctrl.so.$(MAJOR).$(MINOR)
>>    $(SYMLINK_SHLIB) $< $@
>> 
>> libxenctrl.so.$(MAJOR).$(MINOR): $(CTRL_PIC_OBJS)
>> -    $(CC) $(LDFLAGS) $(PTHREAD_LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenctrl.so.$(MAJOR) $(SHLIB_LDFLAGS) -o $@ $^ $(LDLIBS_libxentoollog) $(LDLIBS_libxenevtchn) $(LDLIBS_libxengnttab) $(LDLIBS_libxengntshr) $(DLOPEN_LIBS) $(PTHREAD_LIBS) $(APPEND_LDFLAGS)
>> +    $(CC) $(LDFLAGS) $(PTHREAD_LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenctrl.so.$(MAJOR) $(SHLIB_LDFLAGS) -o $@ $^ $(LDLIBS_libxentoollog) $(LDLIBS_libxenevtchn) $(LDLIBS_libxengnttab) $(LDLIBS_libxengntshr) $(PTHREAD_LIBS) $(APPEND_LDFLAGS)
>> 
>> # libxenguest
>> 
>> @@ -238,8 +228,5 @@ libxenguest.so.$(MAJOR).$(MINOR): COMPRESSION_LIBS = $(call zlib-options,l)
>> libxenguest.so.$(MAJOR).$(MINOR): $(GUEST_PIC_OBJS) libxenctrl.so
>>    $(CC) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenguest.so.$(MAJOR) $(SHLIB_LDFLAGS) -o $@ $(GUEST_PIC_OBJS) $(COMPRESSION_LIBS) -lz $(LDLIBS_libxenevtchn) $(LDLIBS_libxenctrl) $(PTHREAD_LIBS) $(APPEND_LDFLAGS)
>> 
>> -xenctrl_osdep_ENOSYS.so: $(OSDEP_PIC_OBJS) libxenctrl.so
>> -    $(CC) $(LDFLAGS) $(SHLIB_LDFLAGS) -o $@ $(OSDEP_PIC_OBJS) $(LDLIBS_libxenctrl) $(APPEND_LDFLAGS)
>> -
>> -include $(DEPS)
>> 
>> diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h
>> index 9675ebb..61f68bb 100644
>> --- a/tools/libxc/include/xenctrl.h
>> +++ b/tools/libxc/include/xenctrl.h
>> @@ -182,15 +182,6 @@ enum xc_open_flags {
>>  */
>> int xc_interface_close(xc_interface *xch);
>> 
>> -/**
>> - * Query the active OS interface (i.e. that which would be returned by
>> - * xc_interface_open) to find out if it is fake (i.e. backends onto
>> - * something other than an actual Xen hypervisor).
>> - *
>> - * @return 0 is "real", >0 if fake, -1 on error.
>> - */
>> -int xc_interface_is_fake(void);
>> -
>> /*
>>  * HYPERCALL SAFE MEMORY BUFFER
>>  *
>> diff --git a/tools/libxc/include/xenctrlosdep.h b/tools/libxc/include/xenctrlosdep.h
>> deleted file mode 100644
>> index bad10f6..0000000
>> --- a/tools/libxc/include/xenctrlosdep.h
>> +++ /dev/null
>> @@ -1,134 +0,0 @@
>> -/******************************************************************************
>> - *
>> - * Interface to OS specific low-level operations
>> - *
>> - * Copyright (c) 2010, Citrix Systems Inc.
>> - *
>> - * This library 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 of the License.
>> - *
>> - * This library 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.
>> - *
>> - * You should have received a copy of the GNU Lesser General Public
>> - * License along with this library; if not, write to the Free Software
>> - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
>> - */
>> -
>> -/*
>> - * This interface defines the interactions between the Xen control
>> - * libraries and the OS facilities used to communicate with the
>> - * hypervisor.
>> - *
>> - * It is possible to override the default (native) implementation by
>> - * setting the XENCTRL_OSDEP environment variable to point to a
>> - * plugin library. Userspace can use this facility to intercept
>> - * hypervisor operations. This can be used e.g. to implement a
>> - * userspace simulator for Xen hypercalls.
>> - *
>> - * The plugin must contain a data structure:
>> - *  xc_osdep_info_t xc_osdep_info;
>> - *
>> - * xc_osdep_init:
>> - *   Must return a suitable struct xc_osdep_ops pointer or NULL on failure.
>> - */
>> -
>> -#ifndef XC_OSDEP_H
>> -#define XC_OSDEP_H
>> -
>> -/* Tell the Xen public headers we are a user-space tools build. */
>> -#ifndef __XEN_TOOLS__
>> -#define __XEN_TOOLS__ 1
>> -#endif
>> -
>> -#include <sys/mman.h>
>> -#include <sys/types.h>
>> -
>> -#include <xen/sys/privcmd.h>
>> -
>> -enum xc_osdep_type {
>> -    XC_OSDEP_PRIVCMD,
>> -};
>> -
>> -/* Opaque handle internal to the backend */
>> -typedef unsigned long xc_osdep_handle;
>> -
>> -#define XC_OSDEP_OPEN_ERROR ((xc_osdep_handle)-1)
>> -
>> -struct xc_osdep_ops
>> -{
>> -    /* Opens an interface.
>> -     *
>> -     * Must return an opaque handle on success or
>> -     * XC_OSDEP_OPEN_ERROR on failure
>> -     */
>> -    xc_osdep_handle (*open)(xc_interface *xch);
>> -
>> -    int (*close)(xc_interface *xch, xc_osdep_handle h);
>> -
>> -    union {
>> -        struct {
>> -            void *(*alloc_hypercall_buffer)(xc_interface *xch, xc_osdep_handle h, int npages);
>> -            void (*free_hypercall_buffer)(xc_interface *xch, xc_osdep_handle h, void *ptr, int npages);
>> -
>> -            int (*hypercall)(xc_interface *xch, xc_osdep_handle h, privcmd_hypercall_t *hypercall);
>> -
>> -            void *(*map_foreign_batch)(xc_interface *xch, xc_osdep_handle h, uint32_t dom, int prot,
>> -                                       xen_pfn_t *arr, int num);
>> -            void *(*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);
>> -            void *(*map_foreign_range)(xc_interface *xch, xc_osdep_handle h, uint32_t dom, int size, int prot,
>> -                                       unsigned long mfn);
>> -            void *(*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);
>> -        } privcmd;
>> -    } u;
>> -};
>> -typedef struct xc_osdep_ops xc_osdep_ops;
>> -
>> -typedef xc_osdep_ops *(*xc_osdep_init_fn)(xc_interface *xch, enum xc_osdep_type);
>> -
>> -struct xc_osdep_info
>> -{
>> -    /* Describes this backend. */
>> -    const char *name;
>> -
>> -    /* Returns ops function. */
>> -    xc_osdep_init_fn init;
>> -
>> -    /* True if this interface backs onto a fake Xen. */
>> -    int fake;
>> -
>> -    /* For internal use by loader. */
>> -    void *dl_handle;
>> -};
>> -typedef struct xc_osdep_info xc_osdep_info_t;
>> -
>> -/* All backends, including the builtin backend, must supply this structure. */
>> -extern xc_osdep_info_t xc_osdep_info;
>> -
>> -/* Stub for not yet converted OSes */
>> -void *xc_map_foreign_bulk_compat(xc_interface *xch, xc_osdep_handle h,
>> -                                 uint32_t dom, int prot,
>> -                                 const xen_pfn_t *arr, int *err, unsigned int num);
>> -
>> -/* Report errors through xc_interface */
>> -void xc_osdep_log(xc_interface *xch, xentoollog_level level, int code,
>> -                  const char *fmt, ...) __attribute__((format(printf, 4, 5)));
>> -
>> -#endif
>> -
>> -/*
>> - * Local variables:
>> - * mode: C
>> - * c-file-style: "BSD"
>> - * c-basic-offset: 4
>> - * tab-width: 4
>> - * indent-tabs-mode: nil
>> - * End:
>> - */
>> diff --git a/tools/libxc/xc_foreign_memory.c b/tools/libxc/xc_foreign_memory.c
>> index 43abf01..53b6c9a 100644
>> --- a/tools/libxc/xc_foreign_memory.c
>> +++ b/tools/libxc/xc_foreign_memory.c
>> @@ -51,37 +51,8 @@ void *xc_map_foreign_pages(xc_interface *xch, uint32_t dom, int prot,
>>     return res;
>> }
>> 
>> -void *xc_map_foreign_range(xc_interface *xch, uint32_t dom,
>> -                           int size, int prot, unsigned long mfn)
>> -{
>> -    return xch->ops->u.privcmd.map_foreign_range(xch, xch->ops_handle,
>> -                                                 dom, size, prot, mfn);
>> -}
>> -
>> -void *xc_map_foreign_ranges(xc_interface *xch, uint32_t dom,
>> -                            size_t size, int prot, size_t chunksize,
>> -                            privcmd_mmap_entry_t entries[], int nentries)
>> -{
>> -    return xch->ops->u.privcmd.map_foreign_ranges(xch, xch->ops_handle,
>> -                                                  dom, size, prot, chunksize, entries, nentries);
>> -}
>> -
>> -void *xc_map_foreign_batch(xc_interface *xch, uint32_t dom, int prot,
>> -                           xen_pfn_t *arr, int num)
>> -{
>> -    return xch->ops->u.privcmd.map_foreign_batch(xch, xch->ops_handle,
>> -                                                 dom, prot, arr, num);
>> -}
>> -
>> -void *xc_map_foreign_bulk(xc_interface *xch, uint32_t dom, int prot,
>> -                          const xen_pfn_t *arr, int *err, unsigned int num)
>> -{
>> -    return xch->ops->u.privcmd.map_foreign_bulk(xch, xch->ops_handle,
>> -                                                dom, prot, arr, err, num);
>> -}
>> -
>> /* stub for all not yet converted OSes */
>> -void *xc_map_foreign_bulk_compat(xc_interface *xch, xc_osdep_handle h,
>> +void *xc_map_foreign_bulk_compat(xc_interface *xch,
>>                                  uint32_t dom, int prot,
>>                                  const xen_pfn_t *arr, int *err, unsigned int num)
>> {
>> diff --git a/tools/libxc/xc_freebsd_osdep.c b/tools/libxc/xc_freebsd_osdep.c
>> index d948b37..4c0e2fd 100644
>> --- a/tools/libxc/xc_freebsd_osdep.c
>> +++ b/tools/libxc/xc_freebsd_osdep.c
>> @@ -33,16 +33,12 @@
>> 
>> #include <xen/memory.h>
>> 
>> -#include "xenctrl.h"
>> -#include "xenctrlosdep.h"
>> +#include "xc_private.h"
>> 
>> #define PRIVCMD_DEV     "/dev/xen/privcmd"
>> 
>> -#define PERROR(_m, _a...) xc_osdep_log(xch,XTL_ERROR,XC_INTERNAL_ERROR,_m \
>> -                  " (%d = %s)", ## _a , errno, xc_strerror(xch, errno))
>> -
>> /*------------------------- Privcmd device interface -------------------------*/
>> -static xc_osdep_handle freebsd_privcmd_open(xc_interface *xch)
>> +int osdep_privcmd_open(xc_interface *xch)
>> {
>>     int flags, saved_errno;
>>     int fd = open(PRIVCMD_DEV, O_RDWR);
>> @@ -51,7 +47,7 @@ static xc_osdep_handle freebsd_privcmd_open(xc_interface *xch)
>>     {
>>         PERROR("Could not obtain handle on privileged command interface "
>>                PRIVCMD_DEV);
>> -        return XC_OSDEP_OPEN_ERROR;
>> +        return -1
>>     }
>> 
>>     /*
>> @@ -74,27 +70,27 @@ static xc_osdep_handle freebsd_privcmd_open(xc_interface *xch)
>>         goto error;
>>     }
>> 
>> -    return (xc_osdep_handle)fd;
>> +    xch->privcmdfd = fd;
>> +    return 0;
>> 
>>  error:
>>     saved_errno = errno;
>>     close(fd);
>>     errno = saved_errno;
>> 
>> -    return XC_OSDEP_OPEN_ERROR;
>> +    return -1;
>> }
>> 
>> -static int freebsd_privcmd_close(xc_interface *xch, xc_osdep_handle h)
>> +int osdep_privcmd_close(xc_interface *xch)
>> {
>> -    int fd = (int)h;
>> -
>> +    int fd = xch->privcmdfd;
>> +    if ( fd == -1 )
>> +        return 0;
>>     return close(fd);
>> }
>> 
>> /*------------------------ Privcmd hypercall interface -----------------------*/
>> -static void *freebsd_privcmd_alloc_hypercall_buffer(xc_interface *xch,
>> -                                                    xc_osdep_handle h,
>> -                                                    int npages)
>> +void *osdep_alloc_hypercall_buffer(xc_interface *xch, int npages)
>> {
>>     size_t size = npages * XC_PAGE_SIZE;
>>     void *p;
>> @@ -118,9 +114,7 @@ static void *freebsd_privcmd_alloc_hypercall_buffer(xc_interface *xch,
>>     return p;
>> }
>> 
>> -static void freebsd_privcmd_free_hypercall_buffer(xc_interface *xch,
>> -                                                  xc_osdep_handle h, void *ptr,
>> -                                                  int npages)
>> +void osdep_free_hypercall_buffer(xc_interface *xch, void *ptr, int npages)
>> {
>> 
>>     int saved_errno = errno;
>> @@ -132,10 +126,9 @@ static void freebsd_privcmd_free_hypercall_buffer(xc_interface *xch,
>>     errno = saved_errno;
>> }
>> 
>> -static int freebsd_privcmd_hypercall(xc_interface *xch, xc_osdep_handle h,
>> -                                     privcmd_hypercall_t *hypercall)
>> +int do_xen_hypercall(xc_interface *xch, privcmd_hypercall_t *hypercall)
>> {
>> -    int fd = (int)h;
>> +    int fd = xch->privcmdfd;
>>     int ret;
>> 
>>     ret = ioctl(fd, IOCTL_PRIVCMD_HYPERCALL, hypercall);
>> @@ -144,13 +137,12 @@ static int freebsd_privcmd_hypercall(xc_interface *xch, xc_osdep_handle h,
>> }
>> 
>> /*----------------------- Privcmd foreign map interface ----------------------*/
>> -static void *freebsd_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)
>> +void *xc_map_foreign_bulk(xc_interface *xch,
>> +                          uint32_t dom, int prot,
>> +                          const xen_pfn_t *arr, int *err,
>> +                          unsigned int num)
>> {
>> -    int fd = (int)h;
>> +    int fd = xch->privcmdfd;
>>     privcmd_mmapbatch_t ioctlx;
>>     void *addr;
>>     int rc;
>> @@ -181,10 +173,9 @@ static void *freebsd_privcmd_map_foreign_bulk(xc_interface *xch,
>>     return addr;
>> }
>> 
>> -static void *freebsd_privcmd_map_foreign_range(xc_interface *xch,
>> -                                               xc_osdep_handle h,
>> -                                               uint32_t dom, int size, int prot,
>> -                                               unsigned long mfn)
>> +void *xc_map_foreign_range(xc_interface *xch,
>> +                           uint32_t dom, int size, int prot,
>> +                           unsigned long mfn)
>> {
>>     xen_pfn_t *arr;
>>     int num;
>> @@ -204,12 +195,11 @@ static void *freebsd_privcmd_map_foreign_range(xc_interface *xch,
>>     return ret;
>> }
>> 
>> -static void *freebsd_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)
>> +void *xc_map_foreign_ranges(xc_interface *xch,
>> +                            uint32_t dom, size_t size,
>> +                            int prot, size_t chunksize,
>> +                            privcmd_mmap_entry_t entries[],
>> +                            int nentries)
>> {
>>     xen_pfn_t *arr;
>>     int num_per_entry;
>> @@ -233,42 +223,6 @@ static void *freebsd_privcmd_map_foreign_ranges(xc_interface *xch,
>>     return ret;
>> }
>> 
>> -/*----------------------------- Privcmd handlers -----------------------------*/
>> -static struct xc_osdep_ops freebsd_privcmd_ops = {
>> -    .open = &freebsd_privcmd_open,
>> -    .close = &freebsd_privcmd_close,
>> -
>> -    .u.privcmd = {
>> -        .alloc_hypercall_buffer = &freebsd_privcmd_alloc_hypercall_buffer,
>> -        .free_hypercall_buffer = &freebsd_privcmd_free_hypercall_buffer,
>> -
>> -        .hypercall = &freebsd_privcmd_hypercall,
>> -
>> -        .map_foreign_bulk = &freebsd_privcmd_map_foreign_bulk,
>> -        .map_foreign_range = &freebsd_privcmd_map_foreign_range,
>> -        .map_foreign_ranges = &freebsd_privcmd_map_foreign_ranges,
>> -    },
>> -};
>> -
>> -/*---------------------------- FreeBSD interface -----------------------------*/
>> -static struct xc_osdep_ops *
>> -freebsd_osdep_init(xc_interface *xch, enum xc_osdep_type type)
>> -{
>> -    switch ( type )
>> -    {
>> -    case XC_OSDEP_PRIVCMD:
>> -        return &freebsd_privcmd_ops;
>> -    default:
>> -        return NULL;
>> -    }
>> -}
>> -
>> -xc_osdep_info_t xc_osdep_info = {
>> -    .name = "FreeBSD Native OS interface",
>> -    .init = &freebsd_osdep_init,
>> -    .fake = 0,
>> -};
>> -
>> /*
>>  * Local variables:
>>  * mode: C
>> diff --git a/tools/libxc/xc_hcall_buf.c b/tools/libxc/xc_hcall_buf.c
>> index 932b47c..ab8bee5 100644
>> --- a/tools/libxc/xc_hcall_buf.c
>> +++ b/tools/libxc/xc_hcall_buf.c
>> @@ -123,7 +123,7 @@ void xc__hypercall_buffer_cache_release(xc_interface *xch)
>>     while ( xch->hypercall_buffer_cache_nr > 0 )
>>     {
>>         p = xch->hypercall_buffer_cache[--xch->hypercall_buffer_cache_nr];
>> -        xch->ops->u.privcmd.free_hypercall_buffer(xch, xch->ops_handle, p, 1);
>> +        osdep_free_hypercall_buffer(xch, p, 1);
>>     }
>> 
>>     hypercall_buffer_cache_unlock(xch);
>> @@ -134,7 +134,7 @@ void *xc__hypercall_buffer_alloc_pages(xc_interface *xch, xc_hypercall_buffer_t
>>     void *p = hypercall_buffer_cache_alloc(xch, nr_pages);
>> 
>>     if ( !p )
>> -        p = xch->ops->u.privcmd.alloc_hypercall_buffer(xch, xch->ops_handle, nr_pages);
>> +        p = osdep_alloc_hypercall_buffer(xch, nr_pages);
>> 
>>     if (!p)
>>         return NULL;
>> @@ -152,7 +152,7 @@ void xc__hypercall_buffer_free_pages(xc_interface *xch, xc_hypercall_buffer_t *b
>>         return;
>> 
>>     if ( !hypercall_buffer_cache_free(xch, b->hbuf, nr_pages) )
>> -        xch->ops->u.privcmd.free_hypercall_buffer(xch, xch->ops_handle, b->hbuf, nr_pages);
>> +        osdep_free_hypercall_buffer(xch, b->hbuf, nr_pages);
>> }
>> 
>> struct allocation_header {
>> diff --git a/tools/libxc/xc_linux_osdep.c b/tools/libxc/xc_linux_osdep.c
>> index 7246b79..d17a52b 100644
>> --- a/tools/libxc/xc_linux_osdep.c
>> +++ b/tools/libxc/xc_linux_osdep.c
>> @@ -34,13 +34,12 @@
>> #include <xen/memory.h>
>> 
>> #include "xenctrl.h"
>> -#include "xenctrlosdep.h"
>> 
>> #include "xc_private.h"
>> 
>> #define ROUNDUP(_x,_w) (((unsigned long)(_x)+(1UL<<(_w))-1) & ~((1UL<<(_w))-1))
>> 
>> -static xc_osdep_handle linux_privcmd_open(xc_interface *xch)
>> +int osdep_privcmd_open(xc_interface *xch)
>> {
>>     int flags, saved_errno;
>>     int fd = open("/proc/xen/privcmd", O_RDWR);
>> @@ -48,7 +47,7 @@ static xc_osdep_handle linux_privcmd_open(xc_interface *xch)
>>     if ( fd == -1 )
>>     {
>>         PERROR("Could not obtain handle on privileged command interface");
>> -        return XC_OSDEP_OPEN_ERROR;
>> +        return -1;
>>     }
>> 
>>     /* Although we return the file handle as the 'xc handle' the API
>> @@ -69,22 +68,25 @@ static xc_osdep_handle linux_privcmd_open(xc_interface *xch)
>>         goto error;
>>     }
>> 
>> -    return (xc_osdep_handle)fd;
>> +    xch->privcmdfd = fd;
>> +    return 0;
>> 
>>  error:
>>     saved_errno = errno;
>>     close(fd);
>>     errno = saved_errno;
>> -    return XC_OSDEP_OPEN_ERROR;
>> +    return -1;
>> }
>> 
>> -static int linux_privcmd_close(xc_interface *xch, xc_osdep_handle h)
>> +int osdep_privcmd_close(xc_interface *xch)
>> {
>> -    int fd = (int)h;
>> +    int fd = xch->privcmdfd;
>> +    if (fd == -1)
>> +        return 0;
>>     return close(fd);
>> }
>> 
>> -static void *linux_privcmd_alloc_hypercall_buffer(xc_interface *xch, xc_osdep_handle h, int npages)
>> +void *osdep_alloc_hypercall_buffer(xc_interface *xch, int npages)
>> {
>>     size_t size = npages * XC_PAGE_SIZE;
>>     void *p;
>> @@ -116,7 +118,7 @@ out:
>>     return NULL;
>> }
>> 
>> -static void linux_privcmd_free_hypercall_buffer(xc_interface *xch, xc_osdep_handle h, void *ptr, int npages)
>> +void osdep_free_hypercall_buffer(xc_interface *xch, void *ptr, int npages)
>> {
>>     int saved_errno = errno;
>>     /* Recover the VMA flags. Maybe it's not necessary */
>> @@ -127,9 +129,9 @@ static void linux_privcmd_free_hypercall_buffer(xc_interface *xch, xc_osdep_hand
>>     errno = saved_errno;
>> }
>> 
>> -static int linux_privcmd_hypercall(xc_interface *xch, xc_osdep_handle h, privcmd_hypercall_t *hypercall)
>> +int do_xen_hypercall(xc_interface *xch, privcmd_hypercall_t *hypercall)
>> {
>> -    int fd = (int)h;
>> +    int fd = xch->privcmdfd;
>>     return ioctl(fd, IOCTL_PRIVCMD_HYPERCALL, hypercall);
>> }
>> 
>> @@ -155,11 +157,11 @@ static int xc_map_foreign_batch_single(int fd, uint32_t dom,
>>     return rc;
>> }
>> 
>> -static void *linux_privcmd_map_foreign_batch(xc_interface *xch, xc_osdep_handle h,
>> -                                             uint32_t dom, int prot,
>> -                                             xen_pfn_t *arr, int num)
>> +void *xc_map_foreign_batch(xc_interface *xch,
>> +                           uint32_t dom, int prot,
>> +                           xen_pfn_t *arr, int num)
>> {
>> -    int fd = (int)h;
>> +    int fd = xch->privcmdfd;
>>     privcmd_mmapbatch_t ioctlx;
>>     void *addr;
>>     int rc;
>> @@ -261,11 +263,11 @@ out:
>>     return rc;
>> }
>> 
>> -static void *linux_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)
>> +void *xc_map_foreign_bulk(xc_interface *xch,
>> +                          uint32_t dom, int prot,
>> +                          const xen_pfn_t *arr, int *err, unsigned int num)
>> {
>> -    int fd = (int)h;
>> +    int fd = xch->privcmdfd;
>>     privcmd_mmapbatch_v2_t ioctlx;
>>     void *addr;
>>     unsigned int i;
>> @@ -385,9 +387,9 @@ static void *linux_privcmd_map_foreign_bulk(xc_interface *xch, xc_osdep_handle h
>>     return addr;
>> }
>> 
>> -static void *linux_privcmd_map_foreign_range(xc_interface *xch, xc_osdep_handle h,
>> -                                             uint32_t dom, int size, int prot,
>> -                                             unsigned long mfn)
>> +void *xc_map_foreign_range(xc_interface *xch,
>> +                           uint32_t dom, int size, int prot,
>> +                           unsigned long mfn)
>> {
>>     xen_pfn_t *arr;
>>     int num;
>> @@ -407,10 +409,10 @@ static void *linux_privcmd_map_foreign_range(xc_interface *xch, xc_osdep_handle
>>     return ret;
>> }
>> 
>> -static void *linux_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)
>> +void *xc_map_foreign_ranges(xc_interface *xch,
>> +                            uint32_t dom, size_t size, int prot,
>> +                            size_t chunksize, privcmd_mmap_entry_t entries[],
>> +                            int nentries)
>> {
>>     xen_pfn_t *arr;
>>     int num_per_entry;
>> @@ -434,40 +436,6 @@ static void *linux_privcmd_map_foreign_ranges(xc_interface *xch, xc_osdep_handle
>>     return ret;
>> }
>> 
>> -static struct xc_osdep_ops linux_privcmd_ops = {
>> -    .open = &linux_privcmd_open,
>> -    .close = &linux_privcmd_close,
>> -
>> -    .u.privcmd = {
>> -        .alloc_hypercall_buffer = &linux_privcmd_alloc_hypercall_buffer,
>> -        .free_hypercall_buffer = &linux_privcmd_free_hypercall_buffer,
>> -
>> -        .hypercall = &linux_privcmd_hypercall,
>> -
>> -        .map_foreign_batch = &linux_privcmd_map_foreign_batch,
>> -        .map_foreign_bulk = &linux_privcmd_map_foreign_bulk,
>> -        .map_foreign_range = &linux_privcmd_map_foreign_range,
>> -        .map_foreign_ranges = &linux_privcmd_map_foreign_ranges,
>> -    },
>> -};
>> -
>> -static struct xc_osdep_ops *linux_osdep_init(xc_interface *xch, enum xc_osdep_type type)
>> -{
>> -    switch ( type )
>> -    {
>> -    case XC_OSDEP_PRIVCMD:
>> -        return &linux_privcmd_ops;
>> -    default:
>> -        return NULL;
>> -    }
>> -}
>> -
>> -xc_osdep_info_t xc_osdep_info = {
>> -    .name = "Linux Native OS interface",
>> -    .init = &linux_osdep_init,
>> -    .fake = 0,
>> -};
>> -
>> /*
>>  * Local variables:
>>  * mode: C
>> diff --git a/tools/libxc/xc_minios.c b/tools/libxc/xc_minios.c
>> index 947b19a..0a2ac5c 100644
>> --- a/tools/libxc/xc_minios.c
>> +++ b/tools/libxc/xc_minios.c
>> @@ -40,19 +40,20 @@ void minios_interface_close_fd(int fd);
>> 
>> extern void minios_interface_close_fd(int fd);
>> 
>> -static xc_osdep_handle minios_privcmd_open(xc_interface *xch)
>> +int osdep_privcmd_open(xc_interface *xch)
>> {
>>     int fd = alloc_fd(FTYPE_XC);
>> 
>>     if ( fd == -1)
>> -        return XC_OSDEP_OPEN_ERROR;
>> +        return -1;
>> 
>> -    return (xc_osdep_handle)fd;
>> +    xch->privcmdfd = fd;
>> +    return 0;
>> }
>> 
>> -static int minios_privcmd_close(xc_interface *xch, xc_osdep_handle h)
>> +int osdep_privcmd_close(xc_interface *xch)
>> {
>> -    int fd = (int)h;
>> +    int fd = xch->privcmdfd;
>>     return close(fd);
>> }
>> 
>> @@ -61,17 +62,17 @@ void minios_interface_close_fd(int fd)
>>     files[fd].type = FTYPE_NONE;
>> }
>> 
>> -static void *minios_privcmd_alloc_hypercall_buffer(xc_interface *xch, xc_osdep_handle h, int npages)
>> +void *osdep_alloc_hypercall_buffer(xc_interface *xch, int npages)
>> {
>>     return xc_memalign(xch, PAGE_SIZE, npages * PAGE_SIZE);
>> }
>> 
>> -static void minios_privcmd_free_hypercall_buffer(xc_interface *xch, xc_osdep_handle h, void *ptr, int npages)
>> +void osdep_free_hypercall_buffer(xc_interface *xch, void *ptr, int npages)
>> {
>>     free(ptr);
>> }
>> 
>> -static int minios_privcmd_hypercall(xc_interface *xch, xc_osdep_handle h, privcmd_hypercall_t *hypercall)
>> +int do_xen_hypercall(xc_interface *xch, privcmd_hypercall_t *hypercall)
>> {
>>     multicall_entry_t call;
>>     int i, ret;
>> @@ -93,21 +94,21 @@ static int minios_privcmd_hypercall(xc_interface *xch, xc_osdep_handle h, privcm
>>     return call.result;
>> }
>> 
>> -static void *minios_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)
>> +void *xc_map_foreign_bulk(xc_interface *xch,
>> +                          uint32_t dom, int prot,
>> +                          const xen_pfn_t *arr, int *err, unsigned int num)
>> {
>>     unsigned long pt_prot = 0;
>>     if (prot & PROT_READ)
>>    pt_prot = L1_PROT_RO;
>>     if (prot & PROT_WRITE)
>>    pt_prot = L1_PROT;
>> -    return map_frames_ex(arr, num, 1, 0, 1, dom, err, pt_prot);    
>> +    return map_frames_ex(arr, num, 1, 0, 1, dom, err, pt_prot);
>> }
>> 
>> -static void *minios_privcmd_map_foreign_batch(xc_interface *xch,  xc_osdep_handle h,
>> -                                              uint32_t dom, int prot,
>> -                                              xen_pfn_t *arr, int num)
>> +void *xc_map_foreign_batch(xc_interface *xch,
>> +                           uint32_t dom, int prot,
>> +                           xen_pfn_t *arr, int num)
>> {
>>     unsigned long pt_prot = 0;
>>     int err[num];
>> @@ -127,10 +128,10 @@ static void *minios_privcmd_map_foreign_batch(xc_interface *xch,  xc_osdep_handl
>>     return (void *) addr;
>> }
>> 
>> -static void *minios_privcmd_map_foreign_range(xc_interface *xch, xc_osdep_handle h,
>> -                                              uint32_t dom,
>> -                                              int size, int prot,
>> -                                              unsigned long mfn)
>> +void *xc_map_foreign_range(xc_interface *xch,
>> +                           uint32_t dom,
>> +                           int size, int prot,
>> +                           unsigned long mfn)
>> {
>>     unsigned long pt_prot = 0;
>> 
>> @@ -143,10 +144,10 @@ static void *minios_privcmd_map_foreign_range(xc_interface *xch, xc_osdep_handle
>>     return map_frames_ex(&mfn, size / getpagesize(), 0, 1, 1, dom, NULL, pt_prot);
>> }
>> 
>> -static void *minios_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)
>> +void *xc_map_foreign_ranges(xc_interface *xch,
>> +                            uint32_t dom,
>> +                            size_t size, int prot, size_t chunksize,
>> +                            privcmd_mmap_entry_t entries[], int nentries)
>> {
>>     unsigned long *mfns;
>>     int i, j, n;
>> @@ -170,24 +171,6 @@ static void *minios_privcmd_map_foreign_ranges(xc_interface *xch, xc_osdep_handl
>>     return ret;
>> }
>> 
>> -
>> -static struct xc_osdep_ops minios_privcmd_ops = {
>> -    .open = &minios_privcmd_open,
>> -    .close = &minios_privcmd_close,
>> -
>> -    .u.privcmd = {
>> -        .alloc_hypercall_buffer = &minios_privcmd_alloc_hypercall_buffer,
>> -        .free_hypercall_buffer = &minios_privcmd_free_hypercall_buffer,
>> -
>> -        .hypercall = &minios_privcmd_hypercall,
>> -
>> -        .map_foreign_batch = &minios_privcmd_map_foreign_batch,
>> -        .map_foreign_bulk = &minios_privcmd_map_foreign_bulk,
>> -        .map_foreign_range = &minios_privcmd_map_foreign_range,
>> -        .map_foreign_ranges = &minios_privcmd_map_foreign_ranges,
>> -    },
>> -};
>> -
>> /* Optionally flush file to disk and discard page cache */
>> void discard_file_cache(xc_interface *xch, int fd, int flush)
>> {
>> @@ -200,23 +183,6 @@ void *xc_memalign(xc_interface *xch, size_t alignment, size_t size)
>>     return memalign(alignment, size);
>> }
>> 
>> -static struct xc_osdep_ops *minios_osdep_init(xc_interface *xch, enum xc_osdep_type type)
>> -{
>> -    switch ( type )
>> -    {
>> -    case XC_OSDEP_PRIVCMD:
>> -        return &minios_privcmd_ops;
>> -    default:
>> -        return NULL;
>> -    }
>> -}
>> -
>> -xc_osdep_info_t xc_osdep_info = {
>> -    .name = "Minios Native OS interface",
>> -    .init = &minios_osdep_init,
>> -    .fake = 0,
>> -};
>> -
>> /*
>>  * Local variables:
>>  * mode: C
>> diff --git a/tools/libxc/xc_netbsd.c b/tools/libxc/xc_netbsd.c
>> index 48fd5d7..5361f2b 100644
>> --- a/tools/libxc/xc_netbsd.c
>> +++ b/tools/libxc/xc_netbsd.c
>> @@ -25,7 +25,7 @@
>> #include <malloc.h>
>> #include <sys/mman.h>
>> 
>> -static xc_osdep_handle netbsd_privcmd_open(xc_interface *xch)
>> +int osdep_privcmd_open(xc_interface *xch)
>> {
>>     int flags, saved_errno;
>>     int fd = open("/kern/xen/privcmd", O_RDWR);
>> @@ -33,7 +33,7 @@ static xc_osdep_handle netbsd_privcmd_open(xc_interface *xch)
>>     if ( fd == -1 )
>>     {
>>         PERROR("Could not obtain handle on privileged command interface");
>> -        return XC_OSDEP_OPEN_ERROR;
>> +        return -1;
>>     }
>> 
>>     /* Although we return the file handle as the 'xc handle' the API
>> @@ -52,22 +52,23 @@ static xc_osdep_handle netbsd_privcmd_open(xc_interface *xch)
>>         goto error;
>>     }
>> 
>> -    return (xc_osdep_handle)fd;
>> +    xch->privcmdfd = fd;
>> +    return 0;
>> 
>>  error:
>>     saved_errno = errno;
>>     close(fd);
>>     errno = saved_errno;
>> -    return XC_OSDEP_OPEN_ERROR;
>> +    return -1;
>> }
>> 
>> -static int netbsd_privcmd_close(xc_interface *xch, xc_osdep_handle h)
>> +int osdep_privcmd_close(xc_interface *xch)
>> {
>> -    int fd = (int)h;
>> +    int fd = xch->privcmdfd;
>>     return close(fd);
>> }
>> 
>> -static void *netbsd_privcmd_alloc_hypercall_buffer(xc_interface *xch, xc_osdep_handle h, int npages)
>> +void *osdep_alloc_hypercall_buffer(xc_interface *xch, int npages)
>> {
>>     size_t size = npages * XC_PAGE_SIZE;
>>     void *p;
>> @@ -84,15 +85,15 @@ static void *netbsd_privcmd_alloc_hypercall_buffer(xc_interface *xch, xc_osdep_h
>>     return p;
>> }
>> 
>> -static void netbsd_privcmd_free_hypercall_buffer(xc_interface *xch, xc_osdep_handle h, void *ptr, int npages)
>> +void osdep_free_hypercall_buffer(xc_interface *xch, void *ptr, int npages)
>> {
>>     (void) munlock(ptr, npages * XC_PAGE_SIZE);
>>     free(ptr);
>> }
>> 
>> -static int netbsd_privcmd_hypercall(xc_interface *xch, xc_osdep_handle h, privcmd_hypercall_t *hypercall)
>> +int do_xen_hypercall(xc_interface *xch, privcmd_hypercall_t *hypercall)
>> {
>> -    int fd = (int)h;
>> +    int fd = xch->privcmdfd;
>>     int error = ioctl(fd, IOCTL_PRIVCMD_HYPERCALL, hypercall);
>> 
>>     /*
>> @@ -107,11 +108,18 @@ static int netbsd_privcmd_hypercall(xc_interface *xch, xc_osdep_handle h, privcm
>>         return hypercall->retval;
>> }
>> 
>> -static void *netbsd_privcmd_map_foreign_batch(xc_interface *xch, xc_osdep_handle h,
>> -                                              uint32_t dom, int prot,
>> -                                              xen_pfn_t *arr, int num)
>> +void *xc_map_foreign_bulk(xc_interface *xch,
>> +                          uint32_t dom, int prot,
>> +                          const xen_pfn_t *arr, int *err, unsigned int num)
>> {
>> -    int fd = (int)h;
>> +    return xc_map_foreign_bulk_compat(xch, dom, prot, arr, err, num);
>> +}
>> +
>> +void *xc_map_foreign_batch(xc_interface *xch,
>> +                           uint32_t dom, int prot,
>> +                           xen_pfn_t *arr, int num)
>> +{
>> +    int fd = xch->privcmdfd;
>>     privcmd_mmapbatch_t ioctlx;
>>     void *addr;
>>     addr = mmap(NULL, num*XC_PAGE_SIZE, prot, MAP_ANON | MAP_SHARED, -1, 0);
>> @@ -136,12 +144,12 @@ static void *netbsd_privcmd_map_foreign_batch(xc_interface *xch, xc_osdep_handle
>> 
>> }
>> 
>> -static void *netbsd_privcmd_map_foreign_range(xc_interface *xch, xc_osdep_handle h,
>> -                                              uint32_t dom,
>> -                                              int size, int prot,
>> -                                              unsigned long mfn)
>> +void *xc_map_foreign_range(xc_interface *xch,
>> +                           uint32_t dom,
>> +                           int size, int prot,
>> +                           unsigned long mfn)
>> {
>> -    int fd = (int)h;
>> +    int fd = xch->privcmdfd;
>>     privcmd_mmap_t ioctlx;
>>     privcmd_mmap_entry_t entry;
>>     void *addr;
>> @@ -168,12 +176,12 @@ static void *netbsd_privcmd_map_foreign_range(xc_interface *xch, xc_osdep_handle
>>     return addr;
>> }
>> 
>> -static void *netbsd_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)
>> +void *xc_map_foreign_ranges(xc_interface *xch,
>> +                            uint32_t dom,
>> +                            size_t size, int prot, size_t chunksize,
>> +                            privcmd_mmap_entry_t entries[], int nentries)
>> {
>> -    int fd = (int)h;
>> +    int fd = xch->privcmdfd;
>>    privcmd_mmap_t ioctlx;
>>    int i, rc;
>>    void *addr;
>> @@ -206,23 +214,6 @@ mmap_failed:
>>    return NULL;
>> }
>> 
>> -static struct xc_osdep_ops netbsd_privcmd_ops = {
>> -    .open = &netbsd_privcmd_open,
>> -    .close = &netbsd_privcmd_close,
>> -
>> -    .u.privcmd = {
>> -        .alloc_hypercall_buffer = &netbsd_privcmd_alloc_hypercall_buffer,
>> -        .free_hypercall_buffer = &netbsd_privcmd_free_hypercall_buffer,
>> -
>> -        .hypercall = &netbsd_privcmd_hypercall,
>> -
>> -        .map_foreign_batch = &netbsd_privcmd_map_foreign_batch,
>> -        .map_foreign_bulk = &xc_map_foreign_bulk_compat,
>> -        .map_foreign_range = &netbsd_privcmd_map_foreign_range,
>> -        .map_foreign_ranges = &netbsd_privcmd_map_foreign_ranges,
>> -    },
>> -};
>> -
>> /* Optionally flush file to disk and discard page cache */
>> void discard_file_cache(xc_interface *xch, int fd, int flush) 
>> {
>> @@ -263,23 +254,6 @@ void *xc_memalign(xc_interface *xch, size_t alignment, size_t size)
>>     return valloc(size);
>> }
>> 
>> -static struct xc_osdep_ops *netbsd_osdep_init(xc_interface *xch, enum xc_osdep_type type)
>> -{
>> -    switch ( type )
>> -    {
>> -    case XC_OSDEP_PRIVCMD:
>> -        return &netbsd_privcmd_ops;
>> -    default:
>> -        return NULL;
>> -    }
>> -}
>> -
>> -xc_osdep_info_t xc_osdep_info = {
>> -    .name = "Netbsd Native OS interface",
>> -    .init = &netbsd_osdep_init,
>> -    .fake = 0,
>> -};
>> -
>> /*
>>  * Local variables:
>>  * mode: C
>> diff --git a/tools/libxc/xc_private.c b/tools/libxc/xc_private.c
>> index e411210..c56d748 100644
>> --- a/tools/libxc/xc_private.c
>> +++ b/tools/libxc/xc_private.c
>> @@ -27,111 +27,12 @@
>> #include <pthread.h>
>> #include <assert.h>
>> 
>> -#ifndef __MINIOS__
>> -#include <dlfcn.h>
>> -#endif
>> -
>> -#define XENCTRL_OSDEP "XENCTRL_OSDEP"
>> -
>> -#if !defined (__MINIOS__) && !defined(__RUMPUSER_XEN__) && !defined(__RUMPRUN__)
>> -#define DO_DYNAMIC_OSDEP
>> -#endif
>> -
>> -/*
>> - * Returns a (shallow) copy of the xc_osdep_info_t for the
>> - * active OS interface.
>> - *
>> - * On success a handle to the relevant library is opened.  The user
>> - * must subsequently call xc_osdep_put_info() when it is
>> - * finished with the library.
>> - *
>> - * Logs IFF xch != NULL.
>> - *
>> - * Returns:
>> - *  0 - on success
>> - * -1 - on error
>> - */
>> -static int xc_osdep_get_info(xc_interface *xch, xc_osdep_info_t *info)
>> -{
>> -    int rc = -1;
>> -#ifdef DO_DYNAMIC_OSDEP
>> -    const char *lib = getenv(XENCTRL_OSDEP);
>> -    xc_osdep_info_t *pinfo;
>> -    void *dl_handle = NULL;
>> -
>> -    if ( lib != NULL )
>> -    {
>> -        if ( getuid() != geteuid() )
>> -        {
>> -            if ( xch ) ERROR("cannot use %s=%s with setuid application", XENCTRL_OSDEP, lib);
>> -            abort();
>> -        }
>> -        if ( getgid() != getegid() )
>> -        {
>> -            if ( xch ) ERROR("cannot use %s=%s with setgid application", XENCTRL_OSDEP, lib);
>> -            abort();
>> -        }
>> -
>> -        dl_handle = dlopen(lib, RTLD_LAZY|RTLD_LOCAL);
>> -        if ( !dl_handle )
>> -        {
>> -            if ( xch ) ERROR("unable to open osdep library %s: %s", lib, dlerror());
>> -            goto out;
>> -        }
>> -
>> -        pinfo = dlsym(dl_handle, "xc_osdep_info");
>> -        if ( !pinfo )
>> -        {
>> -            if ( xch ) ERROR("unable to find xc_osinteface_info in %s: %s", lib, dlerror());
>> -            goto out;
>> -        }
>> -
>> -        *info = *pinfo;
>> -        info->dl_handle = dl_handle;
>> -    }
>> -    else
>> -#endif /*DO_DYNAMIC_OSDEP*/
>> -    {
>> -        *info = xc_osdep_info;
>> -        info->dl_handle = NULL;
>> -    }
>> -
>> -    rc = 0;
>> -
>> -#ifdef DO_DYNAMIC_OSDEP
>> -out:
>> -    if ( dl_handle && rc == -1 )
>> -        dlclose(dl_handle);
>> -#endif /*DO_DYNAMIC_OSDEP*/
>> -
>> -    return rc;
>> -}
>> -
>> -static void xc_osdep_put(xc_osdep_info_t *info)
>> -{
>> -#ifdef DO_DYNAMIC_OSDEP
>> -    if ( info->dl_handle )
>> -        dlclose(info->dl_handle);
>> -#endif /*DO_DYNAMIC_OSDEP*/
>> -}
>> -
>> -static const char *xc_osdep_type_name(enum xc_osdep_type type)
>> -{
>> -    switch ( type )
>> -    {
>> -    case XC_OSDEP_PRIVCMD: return "privcmd";
>> -    }
>> -    return "unknown";
>> -}
>> -
>> -static struct xc_interface_core *xc_interface_open_common(xentoollog_logger *logger,
>> -                                                          xentoollog_logger *dombuild_logger,
>> -                                                          unsigned open_flags,
>> -                                                          enum xc_osdep_type type)
>> +struct xc_interface_core *xc_interface_open(xentoollog_logger *logger,
>> +                                            xentoollog_logger *dombuild_logger,
>> +                                            unsigned open_flags)
>> {
>>     struct xc_interface_core xch_buf, *xch = &xch_buf;
>> 
>> -    xch->type = type;
>>     xch->flags = open_flags;
>>     xch->dombuild_logger_file = 0;
>>     xc_clear_last_error(xch);
>> @@ -149,9 +50,6 @@ static struct xc_interface_core *xc_interface_open_common(xentoollog_logger *log
>>     xch->hypercall_buffer_cache_misses = 0;
>>     xch->hypercall_buffer_cache_toobig = 0;
>> 
>> -    xch->ops_handle = XC_OSDEP_OPEN_ERROR;
>> -    xch->ops = NULL;
>> -
>>     if (!xch->error_handler) {
>>         xch->error_handler = xch->error_handler_tofree =
>>             (xentoollog_logger*)
>> @@ -169,40 +67,26 @@ static struct xc_interface_core *xc_interface_open_common(xentoollog_logger *log
>>     *xch = xch_buf;
>> 
>>     if (!(open_flags & XC_OPENFLAG_DUMMY)) {
>> -        if ( xc_osdep_get_info(xch, &xch->osdep) < 0 )
>> +        if ( osdep_privcmd_open(xch) < 0 )
>>             goto err;
>> -
>> -        xch->ops = xch->osdep.init(xch, type);
>> -        if ( xch->ops == NULL )
>> -        {
>> -            DPRINTF("OSDEP: interface %d (%s) not supported on this platform",
>> -                  type, xc_osdep_type_name(type));
>> -            goto err_put_iface;
>> -        }
>> -
>> -        xch->ops_handle = xch->ops->open(xch);
>> -        if (xch->ops_handle == XC_OSDEP_OPEN_ERROR)
>> -            goto err_put_iface;
>>     }
>> 
>>     return xch;
>> 
>> -err_put_iface:
>> -    xc_osdep_put(&xch->osdep);
>>  err:
>>     xtl_logger_destroy(xch->error_handler_tofree);
>>     if (xch != &xch_buf) free(xch);
>>     return NULL;
>> }
>> 
>> -static int xc_interface_close_common(xc_interface *xch)
>> +int xc_interface_close(xc_interface *xch)
>> {
>>     int rc = 0;
>> 
>>     if (!xch)
>> -    return 0;
>> +        return 0;
>> 
>> -    rc = xch->ops->close(xch, xch->ops_handle);
>> +    rc = osdep_privcmd_close(xch);
>>     if (rc) PERROR("Could not close hypervisor interface");
>> 
>>     xc__hypercall_buffer_cache_release(xch);
>> @@ -214,42 +98,6 @@ static int xc_interface_close_common(xc_interface *xch)
>>     return rc;
>> }
>> 
>> -int xc_interface_is_fake(void)
>> -{
>> -    xc_osdep_info_t info;
>> -
>> -    if ( xc_osdep_get_info(NULL, &info) < 0 )
>> -        return -1;
>> -
>> -    /* Have a copy of info so can release the interface now. */
>> -    xc_osdep_put(&info);
>> -
>> -    return info.fake;
>> -}
>> -
>> -xc_interface *xc_interface_open(xentoollog_logger *logger,
>> -                                xentoollog_logger *dombuild_logger,
>> -                                unsigned open_flags)
>> -{
>> -    xc_interface *xch;
>> -
>> -    xch = xc_interface_open_common(logger, dombuild_logger, open_flags,
>> -                                   XC_OSDEP_PRIVCMD);
>> -
>> -    return xch;
>> -}
>> -
>> -int xc_interface_close(xc_interface *xch)
>> -{
>> -    return xc_interface_close_common(xch);
>> -}
>> -
>> -
>> -int do_xen_hypercall(xc_interface *xch, privcmd_hypercall_t *hypercall)
>> -{
>> -    return xch->ops->u.privcmd.hypercall(xch, xch->ops_handle, hypercall);
>> -}
>> -
>> static pthread_key_t errbuf_pkey;
>> static pthread_once_t errbuf_pkey_once = PTHREAD_ONCE_INIT;
>> 
>> @@ -336,14 +184,6 @@ void xc_report_error(xc_interface *xch, int code, const char *fmt, ...)
>>     va_end(args);
>> }
>> 
>> -void xc_osdep_log(xc_interface *xch, xentoollog_level level, int code, const char *fmt, ...)
>> -{
>> -    va_list args;
>> -    va_start(args, fmt);
>> -    xc_reportv(xch, xch->error_handler, level, code, fmt, args);
>> -    va_end(args);
>> -}
>> -
>> const char *xc_set_progress_prefix(xc_interface *xch, const char *doing)
>> {
>>     const char *old = xch->currently_progress_reporting;
>> diff --git a/tools/libxc/xc_private.h b/tools/libxc/xc_private.h
>> index 61f2f45..408b1be 100644
>> --- a/tools/libxc/xc_private.h
>> +++ b/tools/libxc/xc_private.h
>> @@ -31,7 +31,6 @@
>> 
>> #include "_paths.h"
>> #include "xenctrl.h"
>> -#include "xenctrlosdep.h"
>> 
>> #include <xen/sys/privcmd.h>
>> 
>> @@ -89,7 +88,6 @@ struct iovec {
>> #define MAX_PAGECACHE_USAGE (4*1024)
>> 
>> struct xc_interface_core {
>> -    enum xc_osdep_type type;
>>     int flags;
>>     xentoollog_logger *error_handler,   *error_handler_tofree;
>>     xentoollog_logger *dombuild_logger, *dombuild_logger_tofree;
>> @@ -118,12 +116,21 @@ struct xc_interface_core {
>>     int hypercall_buffer_cache_misses;
>>     int hypercall_buffer_cache_toobig;
>> 
>> -    /* Low lovel OS interface */
>> -    xc_osdep_info_t  osdep;
>> -    xc_osdep_ops    *ops; /* backend operations */
>> -    xc_osdep_handle  ops_handle; /* opaque data for xc_osdep_ops */
>> +    /* Privcmd interface */
>> +    int privcmdfd;
>> };
>> 
>> +int osdep_privcmd_open(xc_interface *xch);
>> +int osdep_privcmd_close(xc_interface *xch);
>> +
>> +void *osdep_alloc_hypercall_buffer(xc_interface *xch, int npages);
>> +void osdep_free_hypercall_buffer(xc_interface *xch, void *ptr, int npages);
>> +
>> +/* Stub for not yet converted OSes */
>> +void *xc_map_foreign_bulk_compat(xc_interface *xch,
>> +                                 uint32_t dom, int prot,
>> +                                 const xen_pfn_t *arr, int *err, unsigned int num);
>> +
>> void xc_report_error(xc_interface *xch, int code, const char *fmt, ...)
>>     __attribute__((format(printf,3,4)));
>> void xc_reportv(xc_interface *xch, xentoollog_logger *lg, xentoollog_level,
>> diff --git a/tools/libxc/xc_solaris.c b/tools/libxc/xc_solaris.c
>> index 182bd7d..d719a11 100644
>> --- a/tools/libxc/xc_solaris.c
>> +++ b/tools/libxc/xc_solaris.c
>> @@ -25,7 +25,7 @@
>> #include <fcntl.h>
>> #include <malloc.h>
>> 
>> -static xc_osdep_handle solaris_privcmd_open(xc_interface *xch)
>> +int osdep_privcmd_open(xc_interface *xch)
>> {
>>     int flags, saved_errno;
>>     int fd = open("/dev/xen/privcmd", O_RDWR);
>> @@ -33,7 +33,7 @@ static xc_osdep_handle solaris_privcmd_open(xc_interface *xch)
>>     if ( fd == -1 )
>>     {
>>         PERROR("Could not obtain handle on privileged command interface");
>> -        return XC_OSDEP_OPEN_ERROR;
>> +        return -1;
>>     }
>> 
>>     /* Although we return the file handle as the 'xc handle' the API
>> @@ -52,42 +52,43 @@ static xc_osdep_handle solaris_privcmd_open(xc_interface *xch)
>>         goto error;
>>     }
>> 
>> -    return (xc_osdep_handle)fd;
>> +    xch->privcmdfd = fd;
>> +    return 0;
>> 
>>  error:
>>     saved_errno = errno;
>>     close(fd);
>>     errno = saved_errno;
>> -    return XC_OSDEP_OPEN_ERROR;
>> +    return -1;
>> }
>> 
>> -static int solaris_privcmd_close(xc_interface *xch, xc_osdep_handle h)
>> +int osdep_privcmd_close(xc_interface *xch)
>> {
>> -    int fd = (int)h;
>> +    int fd = xch->privcmdfd;
>>     return close(fd);
>> }
>> 
>> -static void *solaris_privcmd_alloc_hypercall_buffer(xc_interface *xch, xc_osdep_handle h, int npages)
>> +void *osdep_alloc_hypercall_buffer(xc_interface *xch, int npages)
>> {
>>     return xc_memalign(xch, XC_PAGE_SIZE, npages * XC_PAGE_SIZE);
>> }
>> 
>> -static void solaris_privcmd_free_hypercall_buffer(xc_interface *xch, xc_osdep_handle h, void *ptr, int npages)
>> +static void osdep_free_hypercall_buffer(xc_interface *xch, void *ptr, int npages)
>> {
>>     free(ptr);
>> }
>> 
>> -static int solaris_privcmd_hypercall(xc_interface *xch, xc_osdep_handle h, privcmd_hypercall_t *hypercall)
>> +int do_xen_hypercall(xc_interface *xch, privcmd_hypercall_t *hypercall)
>> {
>> -    int fd = (int)h;
>> +    int fd = xch->privcmdfd;
>>     return ioctl(fd, IOCTL_PRIVCMD_HYPERCALL, hypercall);
>> }
>> 
>> -static void *solaris_privcmd_map_foreign_batch(xc_interface *xch, xc_osdep_handle h,
>> -                                               uint32_t dom, int prot,
>> -                                               xen_pfn_t *arr, int num)
>> +void *xc_map_foreign_batch(xc_interface *xch,
>> +                          uint32_t dom, int prot,
>> +                          xen_pfn_t *arr, int num)
>> {
>> -    int fd = (int)h;
>> +    int fd = xch->privcmdfd;
>>     privcmd_mmapbatch_t ioctlx;
>>     void *addr;
>>     addr = mmap(NULL, num*XC_PAGE_SIZE, prot, MAP_SHARED, fd, 0);
>> @@ -110,12 +111,19 @@ static void *solaris_privcmd_map_foreign_batch(xc_interface *xch, xc_osdep_handl
>> 
>> }
>> 
>> -static void *xc_map_foreign_range(xc_interface *xch, xc_osdep_handle h,
>> -                                  uint32_t dom,
>> -                                  int size, int prot,
>> -                                  unsigned long mfn)
>> +void *xc_map_foreign_bulk(xc_interface *xch,
>> +                          uint32_t dom, int prot,
>> +                          const xen_pfn_t *arr, int *err, unsigned int num)
>> {
>> -    int fd = (int)fd;
>> +    return xc_map_foreign_bulk_compat(xch, dom, prot, arr, err, num);
>> +}
>> +
>> +void *xc_map_foreign_range(xc_interface *xch,
>> +                           uint32_t dom,
>> +                           int size, int prot,
>> +                           unsigned long mfn)
>> +{
>> +    int fd = xch->privcmdfd;
>>     privcmd_mmap_t ioctlx;
>>     privcmd_mmap_entry_t entry;
>>     void *addr;
>> @@ -139,12 +147,12 @@ static void *xc_map_foreign_range(xc_interface *xch, xc_osdep_handle h,
>>     return addr;
>> }
>> 
>> -static void *solaric_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)
>> +void *xc_map_foreign_ranges(xc_interface *xch,
>> +                            uint32_t dom,
>> +                            size_t size, int prot, size_t chunksize,
>> +                            privcmd_mmap_entry_t entries[], int nentries)
>> {
>> -    int fd = (int)fd;
>> +    int fd = xch->privcmdfd;
>>     privcmd_mmap_t ioctlx;
>>     int i, rc;
>>     void *addr;
>> @@ -177,23 +185,6 @@ mmap_failed:
>>     return NULL;
>> }
>> 
>> -static struct xc_osdep_ops solaris_privcmd_ops = {
>> -    .open = &solaris_privcmd_open,
>> -    .close = &solaris_privcmd_close,
>> -
>> -    .u.privcmd = {
>> -        .alloc_hypercall_buffer = &solaris_privcmd_alloc_hypercall_buffer,
>> -        .free_hypercall_buffer = &solaris_privcmd_free_hypercall_buffer,
>> -
>> -        .hypercall = &solaris_privcmd_hypercall;
>> -
>> -        .map_foreign_batch = &solaris_privcmd_map_foreign_batch,
>> -        .map_foreign_bulk = &xc_map_foreign_bulk_compat,
>> -        .map_foreign_range = &solaris_privcmd_map_foreign_range,
>> -        .map_foreign_ranges = &solaris_privcmd_map_foreign_ranges,
>> -    },
>> -};
>> -
>> /* Optionally flush file to disk and discard page cache */
>> void discard_file_cache(xc_interface *xch, int fd, int flush) 
>> {
>> @@ -205,23 +196,6 @@ void *xc_memalign(xc_interface *xch, size_t alignment, size_t size)
>>     return memalign(alignment, size);
>> }
>> 
>> -static struct xc_osdep_ops *solaris_osdep_init(xc_interface *xch, enum xc_osdep_type type)
>> -{
>> -    switch ( type )
>> -    {
>> -    case XC_OSDEP_PRIVCMD:
>> -        return &solaris_privcmd_ops;
>> -    default:
>> -        return NULL;
>> -    }
>> -}
>> -
>> -xc_osdep_info_t xc_osdep_info = {
>> -    .name = "Solaris Native OS interface",
>> -    .init = &solaris_osdep_init,
>> -    .fake = 0,
>> -};
>> -
>> /*
>>  * Local variables:
>>  * mode: C
>> diff --git a/tools/libxc/xenctrl_osdep_ENOSYS.c b/tools/libxc/xenctrl_osdep_ENOSYS.c
>> deleted file mode 100644
>> index 5182532..0000000
>> --- a/tools/libxc/xenctrl_osdep_ENOSYS.c
>> +++ /dev/null
>> @@ -1,123 +0,0 @@
>> -/* Dummy backend which just logs and returns ENOSYS. */
>> -
>> -#include <errno.h>
>> -#include <inttypes.h>
>> -#include <stdlib.h>
>> -
>> -#include "xenctrl.h"
>> -#include "xenctrlosdep.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))
>> -
>> -static xc_osdep_handle ENOSYS_privcmd_open(xc_interface *xch)
>> -{
>> -    IPRINTF(xch, "ENOSYS_privcmd: opening handle %d\n", 1);
>> -    return (xc_osdep_handle)1; /*dummy*/
>> -}
>> -
>> -static int ENOSYS_privcmd_close(xc_interface *xch, xc_osdep_handle h)
>> -{
>> -    IPRINTF(xch, "ENOSYS_privcmd: closing handle %lx\n", h);
>> -    return 0;
>> -}
>> -
>> -static int ENOSYS_privcmd_hypercall(xc_interface *xch, xc_osdep_handle h, privcmd_hypercall_t *hypercall)
>> -{
>> -#if defined(__FreeBSD__) || defined(__NetBSD__)
>> -    IPRINTF(xch, "ENOSYS_privcmd %lx: hypercall: %02lu(%#lx,%#lx,%#lx,%#lx,%#lx)\n",
>> -#else
>> -    IPRINTF(xch, "ENOSYS_privcmd %lx: hypercall: %02lld(%#llx,%#llx,%#llx,%#llx,%#llx)\n",
>> -#endif
>> -            h, hypercall->op,
>> -            hypercall->arg[0], hypercall->arg[1], hypercall->arg[2],
>> -            hypercall->arg[3], hypercall->arg[4]);
>> -    return -ENOSYS;
>> -}
>> -
>> -static void *ENOSYS_privcmd_map_foreign_batch(xc_interface *xch, xc_osdep_handle h, uint32_t dom, int prot,
>> -                                      xen_pfn_t *arr, int num)
>> -{
>> -    IPRINTF(xch, "ENOSYS_privcmd %lx: map_foreign_batch: dom%d prot %#x arr %p num %d\n", h, dom, prot, arr, num);
>> -    return MAP_FAILED;
>> -}
>> -
>> -static void *ENOSYS_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)
>> -{
>> -    IPRINTF(xch, "ENOSYS_privcmd %lx map_foreign_buld: dom%d prot %#x arr %p err %p num %d\n", h, dom, prot, arr, err, num);
>> -    return MAP_FAILED;
>> -}
>> -
>> -static void *ENOSYS_privcmd_map_foreign_range(xc_interface *xch, xc_osdep_handle h, uint32_t dom, int size, int prot,
>> -                                      unsigned long mfn)
>> -{
>> -    IPRINTF(xch, "ENOSYS_privcmd %lx map_foreign_range: dom%d size %#x prot %#x mfn %ld\n", h, dom, size, prot, mfn);
>> -    return MAP_FAILED;
>> -}
>> -
>> -static void *ENOSYS_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)
>> -{
>> -    IPRINTF(xch, "ENOSYS_privcmd %lx map_foreign_ranges: dom%d size %zd prot %#x chunksize %zd entries %p num %d\n", h, dom, size, prot, chunksize, entries, nentries);
>> -    return MAP_FAILED;
>> -}
>> -
>> -static struct xc_osdep_ops ENOSYS_privcmd_ops =
>> -{
>> -    .open      = &ENOSYS_privcmd_open,
>> -    .close     = &ENOSYS_privcmd_close,
>> -    .u.privcmd   = {
>> -        .hypercall = &ENOSYS_privcmd_hypercall,
>> -
>> -        .map_foreign_batch = &ENOSYS_privcmd_map_foreign_batch,
>> -        .map_foreign_bulk = &ENOSYS_privcmd_map_foreign_bulk,
>> -        .map_foreign_range = &ENOSYS_privcmd_map_foreign_range,
>> -        .map_foreign_ranges = &ENOSYS_privcmd_map_foreign_ranges,
>> -    }
>> -};
>> -
>> -static struct xc_osdep_ops * ENOSYS_osdep_init(xc_interface *xch, enum xc_osdep_type type)
>> -{
>> -    struct xc_osdep_ops *ops;
>> -
>> -    if (getenv("ENOSYS") == NULL)
>> -    {
>> -        PERROR(xch, "ENOSYS: not configured\n");
>> -        return NULL;
>> -    }
>> -
>> -    switch ( type )
>> -    {
>> -    case XC_OSDEP_PRIVCMD:
>> -        ops = &ENOSYS_privcmd_ops;
>> -        break;
>> -    default:
>> -        ops = NULL;
>> -        break;
>> -    }
>> -
>> -    IPRINTF(xch, "ENOSYS_osdep_init: initialising handle ops at %p\n", ops);
>> -
>> -    return ops;
>> -}
>> -
>> -xc_osdep_info_t xc_osdep_info = {
>> -    .name = "Pessimistic ENOSYS OS interface",
>> -    .init = &ENOSYS_osdep_init,
>> -    .fake = 1,
>> -};
>> -
>> -/*
>> - * Local variables:
>> - * mode: C
>> - * c-file-style: "BSD"
>> - * c-basic-offset: 4
>> - * tab-width: 4
>> - * indent-tabs-mode: nil
>> - * End:
>> - */
>> diff --git a/tools/ocaml/libs/xc/xenctrl.ml b/tools/ocaml/libs/xc/xenctrl.ml
>> index b7ba8b7..701b66c 100644
>> --- a/tools/ocaml/libs/xc/xenctrl.ml
>> +++ b/tools/ocaml/libs/xc/xenctrl.ml
>> @@ -108,8 +108,6 @@ external sizeof_xen_pfn: unit -> int = "stub_sizeof_xen_pfn"
>> external interface_open: unit -> handle = "stub_xc_interface_open"
>> external interface_close: handle -> unit = "stub_xc_interface_close"
>> 
>> -external is_fake: unit -> bool = "stub_xc_interface_is_fake"
>> -
>> let with_intf f =
>>    let xc = interface_open () in
>>    let r = try f xc with exn -> interface_close xc; raise exn in
>> diff --git a/tools/ocaml/libs/xc/xenctrl.mli b/tools/ocaml/libs/xc/xenctrl.mli
>> index bc4af56..3f4947c 100644
>> --- a/tools/ocaml/libs/xc/xenctrl.mli
>> +++ b/tools/ocaml/libs/xc/xenctrl.mli
>> @@ -72,7 +72,6 @@ external sizeof_vcpu_guest_context : unit -> int
>>   = "stub_sizeof_vcpu_guest_context"
>> external sizeof_xen_pfn : unit -> int = "stub_sizeof_xen_pfn"
>> external interface_open : unit -> handle = "stub_xc_interface_open"
>> -external is_fake : unit -> bool = "stub_xc_interface_is_fake"
>> external interface_close : handle -> unit = "stub_xc_interface_close"
>> val with_intf : (handle -> 'a) -> 'a
>> val domain_create : handle -> int32 -> domain_create_flag list -> string -> domid
>> diff --git a/tools/ocaml/libs/xc/xenctrl_stubs.c b/tools/ocaml/libs/xc/xenctrl_stubs.c
>> index 64f1137..9a201ee 100644
>> --- a/tools/ocaml/libs/xc/xenctrl_stubs.c
>> +++ b/tools/ocaml/libs/xc/xenctrl_stubs.c
>> @@ -126,13 +126,6 @@ CAMLprim value stub_xc_interface_open(void)
>> }
>> 
>> 
>> -CAMLprim value stub_xc_interface_is_fake(void)
>> -{
>> -    CAMLparam0();
>> -    int is_fake = xc_interface_is_fake();
>> -    CAMLreturn(Val_int(is_fake));
>> -}
>> -
>> CAMLprim value stub_xc_interface_close(value xch)
>> {
>>    CAMLparam1(xch);
>> diff --git a/tools/ocaml/xenstored/domains.ml b/tools/ocaml/xenstored/domains.ml
>> index 92e438f..395f3a9 100644
>> --- a/tools/ocaml/xenstored/domains.ml
>> +++ b/tools/ocaml/xenstored/domains.ml
>> @@ -65,11 +65,9 @@ let create xc doms domid mfn port =
>>    Domain.bind_interdomain dom;
>>    dom
>> 
>> -let create0 fake doms =
>> +let create0 doms =
>>    let port, interface =
>> -        if fake then (
>> -            0, Xenctrl.with_intf (fun xc -> Xenctrl.map_foreign_range xc 0 (Xenmmap.getpagesize()) 0n)
>> -        ) else (
>> +        (
>>            let port = Utils.read_file_single_integer Define.xenstored_proc_port
>>            and fd = Unix.openfile Define.xenstored_proc_kva
>>                           [ Unix.O_RDWR ] 0o600 in
>> diff --git a/tools/ocaml/xenstored/xenstored.ml b/tools/ocaml/xenstored/xenstored.ml
>> index bfe689b..5c7ace1 100644
>> --- a/tools/ocaml/xenstored/xenstored.ml
>> +++ b/tools/ocaml/xenstored/xenstored.ml
>> @@ -176,7 +176,7 @@ let from_channel store cons doms chan =
>>            if domid > 0 then
>>                Domains.create xc doms domid mfn port
>>            else
>> -                Domains.create0 false doms
>> +                Domains.create0 doms
>>            in
>>        Connections.add_domain cons ndom;
>>        in
>> @@ -278,8 +278,7 @@ let _ =
>>            Store.mkdir store (Perms.Connection.create 0) localpath;
>> 
>>        if cf.domain_init then (
>> -            let usingxiu = Xenctrl.is_fake () in
>> -            Connections.add_domain cons (Domains.create0 usingxiu domains);
>> +            Connections.add_domain cons (Domains.create0 domains);
>>            Event.bind_dom_exc_virq eventchn
>>        );
>>    );
>> -- 
>> 2.1.4
>> 

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH XEN v2 09/15] tools/libxc: Remove osdep indirection for privcmd
  2015-07-16  7:59     ` Dave Scott
@ 2015-07-16  8:35       ` Ian Campbell
  0 siblings, 0 replies; 55+ messages in thread
From: Ian Campbell @ 2015-07-16  8:35 UTC (permalink / raw)
  To: Dave Scott
  Cc: Ian Jackson, Roger Pau Monne, Wei Liu, Stefano Stabellini,
	<xen-devel@lists.xen.org>

On Thu, 2015-07-16 at 08:59 +0100, Dave Scott wrote:
[...]
> >> Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
> >> Cc: David Scott <david.scott@citrix.com>
> 
> Confusingly my email is <dave.scott@citrix.com> (‘dave’ rather than
> ‘david’) — best to avoid cc:ing ‘david.scott’ as he probably hasn’t
> got xen-devel email filters set up ;-)

Oh carp, sorry David and Dave! I'll update this branch straight away.

I'll process the rest of the comments and acks etc a bit later...

Ian.


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries
  2015-07-15 15:53 ` [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries Andrew Cooper
@ 2015-07-22 11:12   ` Ian Campbell
  2015-07-22 12:58     ` Andrew Cooper
  2015-07-27  8:57     ` Ian Campbell
  0 siblings, 2 replies; 55+ messages in thread
From: Ian Campbell @ 2015-07-22 11:12 UTC (permalink / raw)
  To: Andrew Cooper, xen-devel
  Cc: minios-devel, Ian Jackson, Roger Pau Monne, Wei Liu, Stefano Stabellini

On Wed, 2015-07-15 at 16:53 +0100, Andrew Cooper wrote:
> 
> > I'm stilling mulling over putting everything into tools/libs/FOO
> > instead of tools/libxenFOO
> 
> On balance, +1.  tools/ is already quite a mixed bag of stuff.

OK, I think I'm going to go ahead with this.

> > , I still haven't but I could if people think
> > it is worthwhile. Eventually I'd like to split libxc into 
> > libxenguest
> > and libxenctrl to cut down on the amount of strange cross talk...
> 
> Very much +1.

OK (eventually ;-))

> FWIW, also splitting xl and libxl into different directories.

Yes, good idea (also "eventually ;-)").

While I'm accumulating TODO items in this thread, every library which
gets split out needs a careful review before it should be declared
A[PBI] stable. I'm thinking at least:

      * Consistent error handling (return -1 + setting errno=EFOO)
      * Correct types
      * Const correctness
      * General interface sanity check

Anything else?

Ian.

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries
  2015-07-22 11:12   ` Ian Campbell
@ 2015-07-22 12:58     ` Andrew Cooper
  2015-07-22 13:05       ` Ian Campbell
  2015-07-27  8:57     ` Ian Campbell
  1 sibling, 1 reply; 55+ messages in thread
From: Andrew Cooper @ 2015-07-22 12:58 UTC (permalink / raw)
  To: Ian Campbell, xen-devel
  Cc: minios-devel, Ian Jackson, Roger Pau Monne, Wei Liu, Stefano Stabellini

On 22/07/15 12:12, Ian Campbell wrote:
>
>> FWIW, also splitting xl and libxl into different directories.
> Yes, good idea (also "eventually ;-)").
>
> While I'm accumulating TODO items in this thread, every library which
> gets split out needs a careful review before it should be declared
> A[PBI] stable. I'm thinking at least:
>
>       * Consistent error handling (return -1 + setting errno=EFOO)
>       * Correct types
>       * Const correctness
>       * General interface sanity check
>
> Anything else?

If we are filling even more copious free time,

* Thoughts about documentation in the header files.

I think a suitably-configured doxygen ought to suffice for this.  (I
feel like I am nominating myself to try and get this sorted in a
satisfactory fashon.)

~Andrew

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries
  2015-07-22 12:58     ` Andrew Cooper
@ 2015-07-22 13:05       ` Ian Campbell
  0 siblings, 0 replies; 55+ messages in thread
From: Ian Campbell @ 2015-07-22 13:05 UTC (permalink / raw)
  To: Andrew Cooper, xen-devel
  Cc: minios-devel, Ian Jackson, Roger Pau Monne, Wei Liu, Stefano Stabellini

On Wed, 2015-07-22 at 13:58 +0100, Andrew Cooper wrote:
> On 22/07/15 12:12, Ian Campbell wrote:
> > 
> > > FWIW, also splitting xl and libxl into different directories.
> > Yes, good idea (also "eventually ;-)").
> > 
> > While I'm accumulating TODO items in this thread, every library 
> > which
> > gets split out needs a careful review before it should be declared
> > A[PBI] stable. I'm thinking at least:
> > 
> >       * Consistent error handling (return -1 + setting errno=EFOO)
> >       * Correct types
> >       * Const correctness
> >       * General interface sanity check
> > 
> > Anything else?
> 
> If we are filling even more copious free time,
> 
> * Thoughts about documentation in the header files.

Yes, I think that would be good. As it happens the stuff being stripped
out is from among the better documented bits of libxc. Surely not
perfect though.

> I think a suitably-configured doxygen ought to suffice for this.  (I
> feel like I am nominating myself to try and get this sorted in a
> satisfactory fashon.)

I think this is rather secondary to accurate comments existing in the
header in some form.

Perhaps rather than doing any work up front it would be better to point
us to an existing example of something produced by what you consider a
suitable-configured doxygen so we can see if we agree?

Ian.

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries
  2015-07-22 11:12   ` Ian Campbell
  2015-07-22 12:58     ` Andrew Cooper
@ 2015-07-27  8:57     ` Ian Campbell
  1 sibling, 0 replies; 55+ messages in thread
From: Ian Campbell @ 2015-07-27  8:57 UTC (permalink / raw)
  To: Andrew Cooper, xen-devel
  Cc: minios-devel, Wei Liu, Stefano Stabellini, Ian Jackson, Roger Pau Monne

On Wed, 2015-07-22 at 12:12 +0100, Ian Campbell wrote:
> On Wed, 2015-07-15 at 16:53 +0100, Andrew Cooper wrote:
> > 
> > > I'm stilling mulling over putting everything into tools/libs/FOO
> > > instead of tools/libxenFOO
> > 
> > On balance, +1.  tools/ is already quite a mixed bag of stuff.
> 
> OK, I think I'm going to go ahead with this.
> 
> > > , I still haven't but I could if people think
> > > it is worthwhile. Eventually I'd like to split libxc into 
> > > libxenguest
> > > and libxenctrl to cut down on the amount of strange cross talk...
> > 
> > Very much +1.
> 
> OK (eventually ;-))
> 
> > FWIW, also splitting xl and libxl into different directories.
> 
> Yes, good idea (also "eventually ;-)").
> 
> While I'm accumulating TODO items in this thread, every library which
> gets split out needs a careful review before it should be declared
> A[PBI] stable. I'm thinking at least:
> 
>       * Consistent error handling (return -1 + setting errno=EFOO)
>       * Correct types
>       * Const correctness
>       * General interface sanity check

Explicit unmap operation to match the foreign map, rather than just
using munmap (to allow valgrind hooks etc).

Ian.

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH XEN v2 05/15] tools: Refactor /dev/xen/evtchn wrappers into libxenevtchn.
  2015-07-15 15:46 ` [PATCH XEN v2 05/15] tools: Refactor /dev/xen/evtchn wrappers into libxenevtchn Ian Campbell
@ 2015-09-21 15:53   ` Ian Campbell
  0 siblings, 0 replies; 55+ messages in thread
From: Ian Campbell @ 2015-09-21 15:53 UTC (permalink / raw)
  To: ian.jackson, wei.liu2, xen-devel; +Cc: roger.pau, stefano.stabellini

On Wed, 2015-07-15 at 16:46 +0100, Ian Campbell wrote:
> diff --git a/tools/libxenevtchn/include/xenevtchn.h
> [...]

> +/* A port identifier is guaranteed to fit in 31 bits. */
> +typedef int evtchn_port_or_error_t;
> 
[...]
> +/*
> + * Returns a new event port awaiting interdomain connection from the given
> + * domain ID, or -1 on failure, in which case errno will be set appropriately.
> + */
> +evtchn_port_or_error_t
> +xenevtchn_bind_unbound_port(xenevtchn_handle *xce, int domid);
> +
> +/*
> + * Returns a new event port bound to the remote port for the given domain ID,
> + * or -1 on failure, in which case errno will be set appropriately.
> + */
> +evtchn_port_or_error_t
> +xenevtchn_bind_interdomain(xenevtchn_handle *xce, int domid,
> +                           evtchn_port_t remote_port);

ISTR that this evtchn_port_or_error_t construct was introduce in order to
correct an incorrect type used here without changing the API in annoying
ways.

Given that this series is already changing the API anyway do we want to
take the opportunity prior to declaring this new library ABI/API stable to
rework these functions such that they return 0 or -1 and take a
evtchn_port_t * output variable which they update on success?

And then abolish evtchn_port_or_error_t except for the
 XC_WANT_COMPAT_EVTCHN_API case.

Ian.

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH XEN v2 08/15] tools: Refactor /dev/xen/gnt{dev, shr} wrappers into libxengnttab.
  2015-07-15 15:46 ` [PATCH XEN v2 08/15] tools: Refactor /dev/xen/gnt{dev, shr} wrappers into libxengnttab Ian Campbell
@ 2015-09-22 11:25   ` Ian Campbell
  2015-09-22 11:36     ` Andrew Cooper
  0 siblings, 1 reply; 55+ messages in thread
From: Ian Campbell @ 2015-09-22 11:25 UTC (permalink / raw)
  To: ian.jackson, wei.liu2, xen-devel; +Cc: roger.pau, stefano.stabellini

Any thoughts/preferences on this library interface regarding:

The use of a (perhaps to be added) grant_ref_t in preference to uint32_t as
it is now?

The use of bool rather than int for "writeable"?

Mapping functions returning NULL on failure (rather than e.g MAP_FAILED)?
(current code squashes any underlying MAP_FAILED into NULL, but of course
that prevents mapping things at NULL, but then I'm not sure why we would
want to support that).

Ian.

On Wed, 2015-07-15 at 16:46 +0100, Ian Campbell wrote:
> diff --git a/tools/libxengnttab/include/xengnttab.h b/tools/libxengnttab/include/xengnttab.h
> new file mode 100644
> index 0000000..b333662
> --- /dev/null
> +++ b/tools/libxengnttab/include/xengnttab.h
> @@ -0,0 +1,215 @@
> +/*
> + * This library 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 of the License.
> + *
> + * This library 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.
> + *
> + * Split off from:
> + * xenctrl.h
> + *
> + * A library for low-level access to the Xen control interfaces.
> + *
> + * Copyright (c) 2007-2008, D G Murray <Derek.Murray@cl.cam.ac.uk>
> + */
> +#ifndef XENGNTTAB_H
> +#define XENGNTTAB_H
> +
> +#include 
> +
> +#include 
> +#include 
> +
> +/* Callers who don't care don't need to #include  */
> +typedef struct xentoollog_logger xentoollog_logger;
> +
> +/*
> + * Grant Table Interface (making use of grants from other domains)
> + */
> +
> +typedef struct xengntdev_handle xengnttab_handle;
> +
> +/*
> + * Note:
> + * After fork a child process must not use any opened xc gnttab
> + * handle inherited from their parent. They must open a new handle if
> + * they want to interact with xc.
> + *
> + * Return an fd onto the grant table driver.  Logs errors.
> + */
> +xengnttab_handle *xengnttab_open(xentoollog_logger *logger, unsigned open_flags);
> +
> +/*
> + * Close a handle previously allocated with xengnttab_open().
> + * Never logs errors.
> + */
> +int xengnttab_close(xengnttab_handle *xgt);
> +
> +/*
> + * Memory maps a grant reference from one domain to a local address range.
> + * Mappings should be unmapped with xengnttab_munmap.  Logs errors.
> + *
> + * @parm xgt a handle on an open grant table interface
> + * @parm domid the domain to map memory from
> + * @parm ref the grant reference ID to map
> + * @parm prot same flag as in mmap()
> + */
> +void *xengnttab_map_grant_ref(xengnttab_handle *xgt,
> +                              uint32_t domid,
> +                              uint32_t ref,
> +                              int prot);
> +
> +/**
> + * Memory maps one or more grant references from one or more domains to a
> + * contiguous local address range. Mappings should be unmapped with
> + * xengnttab_munmap.  Logs errors.
> + *
> + * @parm xgt a handle on an open grant table interface
> + * @parm count the number of grant references to be mapped
> + * @parm domids an array of @count domain IDs by which the corresponding @refs
> + *              were granted
> + * @parm refs an array of @count grant references to be mapped
> + * @parm prot same flag as in mmap()
> + */
> +void *xengnttab_map_grant_refs(xengnttab_handle *xgt,
> +                               uint32_t count,
> +                               uint32_t *domids,
> +                               uint32_t *refs,
> +                               int prot);
> +
> +/**
> + * Memory maps one or more grant references from one domain to a
> + * contiguous local address range. Mappings should be unmapped with
> + * xengnttab_munmap.  Logs errors.
> + *
> + * @parm xgt a handle on an open grant table interface
> + * @parm count the number of grant references to be mapped
> + * @parm domid the domain to map memory from
> + * @parm refs an array of @count grant references to be mapped
> + * @parm prot same flag as in mmap()
> + */
> +void *xengnttab_map_domain_grant_refs(xengnttab_handle *xgt,
> +                                      uint32_t count,
> +                                      uint32_t domid,
> +                                      uint32_t *refs,
> +                                      int prot);
> +
> +/**
> + * Memory maps a grant reference from one domain to a local address range.
> + * Mappings should be unmapped with xengnttab_munmap. If notify_offset or
> + * notify_port are not -1, this version will attempt to set up an unmap
> + * notification at the given offset and event channel. When the page is
> + * unmapped, the byte at the given offset will be zeroed and a wakeup will be
> + * sent to the given event channel.  Logs errors.
> + *
> + * @parm xgt a handle on an open grant table interface
> + * @parm domid the domain to map memory from
> + * @parm ref the grant reference ID to map
> + * @parm prot same flag as in mmap()
> + * @parm notify_offset The byte offset in the page to use for unmap
> + *                     notification; -1 for none.
> + * @parm notify_port The event channel port to use for unmap notify, or -1
> + */
> +void *xengnttab_map_grant_ref_notify(xengnttab_handle *xgt,
> +                                     uint32_t domid,
> +                                     uint32_t ref,
> +                                     int prot,
> +                                     uint32_t notify_offset,
> +                                     evtchn_port_t notify_port);
> +
> +/*
> + * Unmaps the @count pages starting at @start_address, which were mapped by a
> + * call to xengnttab_map_grant_ref or xengnttab_map_grant_refs. Never logs.
> + */
> +int xengnttab_munmap(xengnttab_handle *xgt,
> +                     void *start_address,
> +                     uint32_t count);
> +
> +/*
> + * Sets the maximum number of grants that may be mapped by the given instance
> + * to @count.  Never logs.
> + *
> + * N.B. This function must be called after opening the handle, and before any
> + *      other functions are invoked on it.
> + *
> + * N.B. When variable-length grants are mapped, fragmentation may be observed,
> + *      and it may not be possible to satisfy requests up to the maximum number
> + *      of grants.
> + */
> +int xengnttab_set_max_grants(xengnttab_handle *xgt,
> +                            uint32_t count);
> +
> +/*
> + * Grant Sharing Interface (allocating and granting pages)
> + */
> +
> +typedef struct xengntdev_handle xengntshr_handle;
> +
> +/*
> + * Return an fd onto the grant sharing driver.  Logs errors.
> + *
> + * Note:
> + * After fork a child process must not use any opened xc gntshr
> + * handle inherited from their parent. They must open a new handle if
> + * they want to interact with xc.
> + *
> + */
> +xengntshr_handle *xengntshr_open(xentoollog_logger *logger,
> +                         unsigned open_flags);
> +
> +/*
> + * Close a handle previously allocated with xengntshr_open().
> + * Never logs errors.
> + */
> +int xengntshr_close(xengntshr_handle *xgs);
> +
> +/*
> + * Creates and shares pages with another domain.
> + *
> + * @parm xgs a handle to an open grant sharing instance
> + * @parm domid the domain to share memory with
> + * @parm count the number of pages to share
> + * @parm refs the grant references of the pages (output)
> + * @parm writable true if the other domain can write to the pages
> + * @return local mapping of the pages
> + */
> +void *xengntshr_share_pages(xengntshr_handle *xgs, uint32_t domid,
> +                            int count, uint32_t *refs, int writable);
> +
> +/*
> + * Creates and shares a page with another domain, with unmap notification.
> + *
> + * @parm xgs a handle to an open grant sharing instance
> + * @parm domid the domain to share memory with
> + * @parm refs the grant reference of the pages (output)
> + * @parm writable true if the other domain can write to the page
> + * @parm notify_offset The byte offset in the page to use for unmap
> + *                     notification; -1 for none.
> + * @parm notify_port The event channel port to use for unmap notify, or -1
> + * @return local mapping of the page
> + */
> +void *xengntshr_share_page_notify(xengntshr_handle *xgs, uint32_t domid,
> +                                  uint32_t *ref, int writable,
> +                                  uint32_t notify_offset,
> +                                  evtchn_port_t notify_port);
> +/*
> + * Unmaps the @count pages starting at @start_address, which were mapped by a
> + * call to xengntshr_share_*. Never logs.
> + */
> +int xengntshr_munmap(xengntshr_handle *xgs, void *start_address, uint32_t count);
> +
> +#endif
> +
> +/*
> + * Local variables:
> + * mode: C
> + * c-file-style: "BSD"
> + * c-basic-offset: 4
> + * tab-width: 4
> + * indent-tabs-mode: nil
> + * End:
> + */

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH XEN v2 08/15] tools: Refactor /dev/xen/gnt{dev, shr} wrappers into libxengnttab.
  2015-09-22 11:25   ` Ian Campbell
@ 2015-09-22 11:36     ` Andrew Cooper
  2015-09-22 12:41       ` Ian Jackson
  0 siblings, 1 reply; 55+ messages in thread
From: Andrew Cooper @ 2015-09-22 11:36 UTC (permalink / raw)
  To: Ian Campbell, ian.jackson, wei.liu2, xen-devel
  Cc: stefano.stabellini, roger.pau

On 22/09/15 12:25, Ian Campbell wrote:
> Any thoughts/preferences on this library interface regarding:
>
> The use of a (perhaps to be added) grant_ref_t in preference to uint32_t as
> it is now?

Probably a good idea.  We should also introduce/use domid_t consistently 
through the new API as well.

>
> The use of bool rather than int for "writeable"?

Depends if we go for -std=c89 or -std=c99.

Given that it is 2015, I vote for -std=c99 and all the niceties it 
brings, such as bool.

>
> Mapping functions returning NULL on failure (rather than e.g MAP_FAILED)?
> (current code squashes any underlying MAP_FAILED into NULL, but of course
> that prevents mapping things at NULL, but then I'm not sure why we would
> want to support that).

+1

Anyone code choosing to try and map a grant ref at 0 can handcode the 
systemcalls itself.  Sane software will be much happier with NULL as the 
failure check.

~Andrew

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH XEN v2 08/15] tools: Refactor /dev/xen/gnt{dev, shr} wrappers into libxengnttab.
  2015-09-22 11:36     ` Andrew Cooper
@ 2015-09-22 12:41       ` Ian Jackson
  2015-09-22 12:51         ` Ian Campbell
  0 siblings, 1 reply; 55+ messages in thread
From: Ian Jackson @ 2015-09-22 12:41 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: roger.pau, wei.liu2, Ian Campbell, stefano.stabellini, xen-devel

Andrew Cooper writes ("Re: [Xen-devel] [PATCH XEN v2 08/15] tools: Refactor /dev/xen/gnt{dev, shr} wrappers into libxengnttab."):
> On 22/09/15 12:25, Ian Campbell wrote:
> > Any thoughts/preferences on this library interface regarding:
> >
> > The use of a (perhaps to be added) grant_ref_t in preference to uint32_t as
> > it is now?

Is a grant_ref_t uint32_t ?

> Probably a good idea.  We should also introduce/use domid_t consistently 
> through the new API as well.

domid_it is a uint16_t.  The problem with that is that there is no
space for sentinel or magic values which are assigned meanings outside
the hypervisor.

> Given that it is 2015, I vote for -std=c99 and all the niceties it 
> brings, such as bool.

We should certainly consider some GNU extensions.  I don't know which
are widely available, but we should consider:
 * Statement expressions
 * Some of the function and data attributes, particularly
   format, noreturn, unused.  (Maybe via some compatibility macros.)
 * Anonymous struct/union members.
 * typeof

Ian.

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH XEN v2 08/15] tools: Refactor /dev/xen/gnt{dev, shr} wrappers into libxengnttab.
  2015-09-22 12:41       ` Ian Jackson
@ 2015-09-22 12:51         ` Ian Campbell
  0 siblings, 0 replies; 55+ messages in thread
From: Ian Campbell @ 2015-09-22 12:51 UTC (permalink / raw)
  To: Ian Jackson, Andrew Cooper
  Cc: roger.pau, wei.liu2, stefano.stabellini, xen-devel

On Tue, 2015-09-22 at 13:41 +0100, Ian Jackson wrote:
> Andrew Cooper writes ("Re: [Xen-devel] [PATCH XEN v2 08/15] tools:
> Refactor /dev/xen/gnt{dev, shr} wrappers into libxengnttab."):
> > On 22/09/15 12:25, Ian Campbell wrote:
> > > Any thoughts/preferences on this library interface regarding:
> > > 
> > > The use of a (perhaps to be added) grant_ref_t in preference to
> > > uint32_t as
> > > it is now?
> 
> Is a grant_ref_t uint32_t ?

Yes (in xen/include/public/grant_table.h).

> > Probably a good idea.  We should also introduce/use domid_t
> > consistently 
> > through the new API as well.
> 
> domid_it is a uint16_t.  The problem with that is that there is no
> space for sentinel or magic values which are assigned meanings outside
> the hypervisor.

Correct.

We don't necessarily need to use the same domid_t as the hypervisor
interface, but not doing so would seem confusing...

> > Given that it is 2015, I vote for -std=c99 and all the niceties it 
> > brings, such as bool.
> 
> We should certainly consider some GNU extensions.  I don't know which
> are widely available, but we should consider:
>  * Statement expressions
>  * Some of the function and data attributes, particularly
>    format, noreturn, unused.  (Maybe via some compatibility macros.)
>  * Anonymous struct/union members.
>  * typeof

For the implementation side, sure, few of these seem relevant to the
interface headers being discussed here (apart maybe from anon members,
which is moot because none of the libraries in question have a need for
such a thing AFAICT).

Ian.

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Oldest supported Xen version in upstream QEMU (Was: Re: [Minios-devel] [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries)
  2015-07-15 15:46 [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries Ian Campbell
                   ` (25 preceding siblings ...)
  2015-07-15 15:53 ` [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries Andrew Cooper
@ 2015-09-22 15:03 ` Ian Campbell
  2015-09-22 21:31   ` Stefano Stabellini
  2015-09-24 16:47 ` [Minios-devel] [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries Ian Campbell
  27 siblings, 1 reply; 55+ messages in thread
From: Ian Campbell @ 2015-09-22 15:03 UTC (permalink / raw)
  To: xen-devel, Stefano Stabellini; +Cc: Ian Jackson, Wei Liu, Roger Pau Monne

(dropping minios-devel)

Stefano,

On Wed, 2015-07-15 at 16:46 +0100, Ian Campbell wrote:
> 
> There are 3 series, against xen.git (15 patches), mini-os.git (5
> patches) and qemu-xen-trad.git (5 patches). The patches against xen.git
> point to the patches in the other two trees via instructions to update
> the relevant Config.mk field. The perils of changing unstable
> interfaces!

I started looking into making the appropriate changes to QEMU upstream to
use the new libraries directly.

QEMU (in include/hw/xen/xen_common.h) includes compat shims for libxenctrl
versions back as far as 3.3.0.

The main distinction is between pre-4.1.0 and 4.1.0 and later, since
various handles switching from int's to opaque pointers at that point,
meaning there are some typedefs and wrappers for things.

My plan was to rework the QEMU code to use only the new library function
names for everything such that this becomes the default case (which makes
sense given these libraries are intended to be long term stable) and to
update the code in xen_common.h to bridge the gap to 4.6 and earlier.

But I'm having to jump through some hoops in order to support the pre-4.1.0
version of things. It's not impossible to support it, I'm sure, but things
would be a lot easier if we could just drop that support code.

Can we consider dropping support for Xen 4.0 and earlier from upstream QEMU
at this point?

Some data: Xen 4.0.0 was released in April 2010, the last point release was
4.0.4 in August 2012 and we no longer do security support for it (for a
year or two now, I think).

Thanks,
Ian.

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Oldest supported Xen version in upstream QEMU (Was: Re: [Minios-devel] [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries)
  2015-09-22 15:03 ` Oldest supported Xen version in upstream QEMU (Was: Re: [Minios-devel] [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries) Ian Campbell
@ 2015-09-22 21:31   ` Stefano Stabellini
  2015-09-23  8:29     ` Ian Campbell
  0 siblings, 1 reply; 55+ messages in thread
From: Stefano Stabellini @ 2015-09-22 21:31 UTC (permalink / raw)
  To: Ian Campbell
  Cc: Ian Jackson, Stefano Stabellini, Wei Liu, Roger Pau Monne, xen-devel

On Tue, 22 Sep 2015, Ian Campbell wrote:
> (dropping minios-devel)
> 
> Stefano,
> 
> On Wed, 2015-07-15 at 16:46 +0100, Ian Campbell wrote:
> > 
> > There are 3 series, against xen.git (15 patches), mini-os.git (5
> > patches) and qemu-xen-trad.git (5 patches). The patches against xen.git
> > point to the patches in the other two trees via instructions to update
> > the relevant Config.mk field. The perils of changing unstable
> > interfaces!
> 
> I started looking into making the appropriate changes to QEMU upstream to
> use the new libraries directly.
> 
> QEMU (in include/hw/xen/xen_common.h) includes compat shims for libxenctrl
> versions back as far as 3.3.0.
> 
> The main distinction is between pre-4.1.0 and 4.1.0 and later, since
> various handles switching from int's to opaque pointers at that point,
> meaning there are some typedefs and wrappers for things.
> 
> My plan was to rework the QEMU code to use only the new library function
> names for everything such that this becomes the default case (which makes
> sense given these libraries are intended to be long term stable) and to
> update the code in xen_common.h to bridge the gap to 4.6 and earlier.
> 
> But I'm having to jump through some hoops in order to support the pre-4.1.0
> version of things. It's not impossible to support it, I'm sure, but things
> would be a lot easier if we could just drop that support code.
> 
> Can we consider dropping support for Xen 4.0 and earlier from upstream QEMU
> at this point?
> 
> Some data: Xen 4.0.0 was released in April 2010, the last point release was
> 4.0.4 in August 2012 and we no longer do security support for it (for a
> year or two now, I think).
 
The oldest Xen version I build-test for every pull request is Xen 4.0.0,
I think it is very reasonable to remove anything older than that.
I am OK with removing Xen 4.0.0 too, but I would like a warning to be
sent ahead of time to qemu-devel to see if anybody complains.

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Oldest supported Xen version in upstream QEMU (Was: Re: [Minios-devel] [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries)
  2015-09-22 21:31   ` Stefano Stabellini
@ 2015-09-23  8:29     ` Ian Campbell
  2015-09-23 14:09       ` Konrad Rzeszutek Wilk
  2015-09-23 17:36       ` Stefano Stabellini
  0 siblings, 2 replies; 55+ messages in thread
From: Ian Campbell @ 2015-09-23  8:29 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: Ian Jackson, Roger Pau Monne, Wei Liu, xen-devel

On Tue, 2015-09-22 at 22:31 +0100, Stefano Stabellini wrote: 
> The oldest Xen version I build-test for every pull request is Xen 4.0.0,
> I think it is very reasonable to remove anything older than that.
> I am OK with removing Xen 4.0.0 too, but I would like a warning to be
> sent ahead of time to qemu-devel to see if anybody complains.

There is not much point in removing <=3.4 support and keeping 4.0, since
4.0.0 was the last one which used a plain int as a handle, anything older
than 4.0.0 is trivial if 4.0.0 is supported.

One approach I am considering in order to keep 4.0.0 support and earlier
was to turn the "int fd" for <=4.0 into a pointer by having the open
wrapper do malloc(sizeof int) and the using wrappers do xc_foo(*handle).

This way all the different variants take pointers and we have less hoops to
jump through to typedef everything in the correct way for each variant.

If you would rather avoid doing that then I think dropping 4.0.0 support
would be the way to go and I'll send a mail to qemu-devel.

Ian.

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Oldest supported Xen version in upstream QEMU (Was: Re: [Minios-devel] [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries)
  2015-09-23  8:29     ` Ian Campbell
@ 2015-09-23 14:09       ` Konrad Rzeszutek Wilk
  2015-09-23 14:17         ` Juergen Gross
  2015-09-23 17:36       ` Stefano Stabellini
  1 sibling, 1 reply; 55+ messages in thread
From: Konrad Rzeszutek Wilk @ 2015-09-23 14:09 UTC (permalink / raw)
  To: Ian Campbell
  Cc: Wei Liu, xen-devel, Roger Pau Monne, Ian Jackson, Stefano Stabellini

On Wed, Sep 23, 2015 at 09:29:10AM +0100, Ian Campbell wrote:
> On Tue, 2015-09-22 at 22:31 +0100, Stefano Stabellini wrote: 
> > The oldest Xen version I build-test for every pull request is Xen 4.0.0,
> > I think it is very reasonable to remove anything older than that.
> > I am OK with removing Xen 4.0.0 too, but I would like a warning to be
> > sent ahead of time to qemu-devel to see if anybody complains.
> 
> There is not much point in removing <=3.4 support and keeping 4.0, since
> 4.0.0 was the last one which used a plain int as a handle, anything older
> than 4.0.0 is trivial if 4.0.0 is supported.
> 
> One approach I am considering in order to keep 4.0.0 support and earlier
> was to turn the "int fd" for <=4.0 into a pointer by having the open
> wrapper do malloc(sizeof int) and the using wrappers do xc_foo(*handle).
> 
> This way all the different variants take pointers and we have less hoops to
> jump through to typedef everything in the correct way for each variant.
> 
> If you would rather avoid doing that then I think dropping 4.0.0 support
> would be the way to go and I'll send a mail to qemu-devel.

Perhaps to help in killing the 4.0.0 support - Linux pvops can't work
with Xen 4.0.0 - sadly I don't recall the details but I think it was missing
an hypercall.
> 
> Ian.
> 
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xen.org
> http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Oldest supported Xen version in upstream QEMU (Was: Re: [Minios-devel] [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries)
  2015-09-23 14:09       ` Konrad Rzeszutek Wilk
@ 2015-09-23 14:17         ` Juergen Gross
  2015-09-23 14:21           ` Konrad Rzeszutek Wilk
  0 siblings, 1 reply; 55+ messages in thread
From: Juergen Gross @ 2015-09-23 14:17 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk, Ian Campbell
  Cc: Ian Jackson, Roger Pau Monne, Wei Liu, Stefano Stabellini, xen-devel

On 09/23/2015 04:09 PM, Konrad Rzeszutek Wilk wrote:
> On Wed, Sep 23, 2015 at 09:29:10AM +0100, Ian Campbell wrote:
>> On Tue, 2015-09-22 at 22:31 +0100, Stefano Stabellini wrote:
>>> The oldest Xen version I build-test for every pull request is Xen 4.0.0,
>>> I think it is very reasonable to remove anything older than that.
>>> I am OK with removing Xen 4.0.0 too, but I would like a warning to be
>>> sent ahead of time to qemu-devel to see if anybody complains.
>>
>> There is not much point in removing <=3.4 support and keeping 4.0, since
>> 4.0.0 was the last one which used a plain int as a handle, anything older
>> than 4.0.0 is trivial if 4.0.0 is supported.
>>
>> One approach I am considering in order to keep 4.0.0 support and earlier
>> was to turn the "int fd" for <=4.0 into a pointer by having the open
>> wrapper do malloc(sizeof int) and the using wrappers do xc_foo(*handle).
>>
>> This way all the different variants take pointers and we have less hoops to
>> jump through to typedef everything in the correct way for each variant.
>>
>> If you would rather avoid doing that then I think dropping 4.0.0 support
>> would be the way to go and I'll send a mail to qemu-devel.
>
> Perhaps to help in killing the 4.0.0 support - Linux pvops can't work
> with Xen 4.0.0 - sadly I don't recall the details but I think it was missing
> an hypercall.

Are you sure? On the Xen developer summit this year I asked a guy from
Amazon whether they are testing upstream pvops kernels on all Xen
versions they support, and he confirmed that. And they do support Xen
4.0 and older.


Juergen

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Oldest supported Xen version in upstream QEMU (Was: Re: [Minios-devel] [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries)
  2015-09-23 14:17         ` Juergen Gross
@ 2015-09-23 14:21           ` Konrad Rzeszutek Wilk
  2015-09-23 14:26             ` Ian Campbell
  0 siblings, 1 reply; 55+ messages in thread
From: Konrad Rzeszutek Wilk @ 2015-09-23 14:21 UTC (permalink / raw)
  To: Juergen Gross
  Cc: Wei Liu, Ian Campbell, Stefano Stabellini, Ian Jackson,
	xen-devel, Roger Pau Monne

On Wed, Sep 23, 2015 at 04:17:05PM +0200, Juergen Gross wrote:
> On 09/23/2015 04:09 PM, Konrad Rzeszutek Wilk wrote:
> >On Wed, Sep 23, 2015 at 09:29:10AM +0100, Ian Campbell wrote:
> >>On Tue, 2015-09-22 at 22:31 +0100, Stefano Stabellini wrote:
> >>>The oldest Xen version I build-test for every pull request is Xen 4.0.0,
> >>>I think it is very reasonable to remove anything older than that.
> >>>I am OK with removing Xen 4.0.0 too, but I would like a warning to be
> >>>sent ahead of time to qemu-devel to see if anybody complains.
> >>
> >>There is not much point in removing <=3.4 support and keeping 4.0, since
> >>4.0.0 was the last one which used a plain int as a handle, anything older
> >>than 4.0.0 is trivial if 4.0.0 is supported.
> >>
> >>One approach I am considering in order to keep 4.0.0 support and earlier
> >>was to turn the "int fd" for <=4.0 into a pointer by having the open
> >>wrapper do malloc(sizeof int) and the using wrappers do xc_foo(*handle).
> >>
> >>This way all the different variants take pointers and we have less hoops to
> >>jump through to typedef everything in the correct way for each variant.
> >>
> >>If you would rather avoid doing that then I think dropping 4.0.0 support
> >>would be the way to go and I'll send a mail to qemu-devel.
> >
> >Perhaps to help in killing the 4.0.0 support - Linux pvops can't work
> >with Xen 4.0.0 - sadly I don't recall the details but I think it was missing
> >an hypercall.
> 
> Are you sure? On the Xen developer summit this year I asked a guy from

And I am incorrect (from http://wiki.xen.org/wiki/Dom0_Kernels_for_Xen):

	"Q: I've seen mentions of 'pv_ops' and 'xenlinux' kernels. Which one
	should I choose?

	Simple answer: pv_ops. Xen Project 4.0 switched to using Linux pv_ops
	based dom0 kernel as a default.."

> Amazon whether they are testing upstream pvops kernels on all Xen
> versions they support, and he confirmed that. And they do support Xen
> 4.0 and older.

Oh gosh, older than 4.0? Ugh.

> 
> 
> Juergen
> 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Oldest supported Xen version in upstream QEMU (Was: Re: [Minios-devel] [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries)
  2015-09-23 14:21           ` Konrad Rzeszutek Wilk
@ 2015-09-23 14:26             ` Ian Campbell
  0 siblings, 0 replies; 55+ messages in thread
From: Ian Campbell @ 2015-09-23 14:26 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk, Juergen Gross
  Cc: Ian Jackson, Roger Pau Monne, Wei Liu, Stefano Stabellini, xen-devel

On Wed, 2015-09-23 at 10:21 -0400, Konrad Rzeszutek Wilk wrote:
> On Wed, Sep 23, 2015 at 04:17:05PM +0200, Juergen Gross wrote:
> > On 09/23/2015 04:09 PM, Konrad Rzeszutek Wilk wrote:
> > > On Wed, Sep 23, 2015 at 09:29:10AM +0100, Ian Campbell wrote:
> > > > On Tue, 2015-09-22 at 22:31 +0100, Stefano Stabellini wrote:
> > > > > The oldest Xen version I build-test for every pull request is Xen
> > > > > 4.0.0,
> > > > > I think it is very reasonable to remove anything older than that.
> > > > > I am OK with removing Xen 4.0.0 too, but I would like a warning
> > > > > to be
> > > > > sent ahead of time to qemu-devel to see if anybody complains.
> > > > 
> > > > There is not much point in removing <=3.4 support and keeping 4.0,
> > > > since
> > > > 4.0.0 was the last one which used a plain int as a handle, anything
> > > > older
> > > > than 4.0.0 is trivial if 4.0.0 is supported.
> > > > 
> > > > One approach I am considering in order to keep 4.0.0 support and
> > > > earlier
> > > > was to turn the "int fd" for <=4.0 into a pointer by having the
> > > > open
> > > > wrapper do malloc(sizeof int) and the using wrappers do
> > > > xc_foo(*handle).
> > > > 
> > > > This way all the different variants take pointers and we have less
> > > > hoops to
> > > > jump through to typedef everything in the correct way for each
> > > > variant.
> > > > 
> > > > If you would rather avoid doing that then I think dropping 4.0.0
> > > > support
> > > > would be the way to go and I'll send a mail to qemu-devel.
> > > 
> > > Perhaps to help in killing the 4.0.0 support - Linux pvops can't work
> > > with Xen 4.0.0 - sadly I don't recall the details but I think it was
> > > missing
> > > an hypercall.
> > 
> > Are you sure? On the Xen developer summit this year I asked a guy from
> 
> And I am incorrect (from http://wiki.xen.org/wiki/Dom0_Kernels_for_Xen):
> 
> 	"Q: I've seen mentions of 'pv_ops' and 'xenlinux' kernels. Which
> one
> 	should I choose?
> 
> 	Simple answer: pv_ops. Xen Project 4.0 switched to using Linux
> pv_ops
> 	based dom0 kernel as a default.."

This contracts your hypothesis, it says that Xen 4.0 is expected to work
with a pvops dom0 (or else we wouldn't have switched to it by default).

I think the cut off you are thinking of was a bit older, e.g. 3.4 or so.

> 
> > Amazon whether they are testing upstream pvops kernels on all Xen
> > versions they support, and he confirmed that. And they do support Xen
> > 4.0 and older.

NB they presumably care about domU only for this testing, whereas whatever
the incompatibility is it was to do with dom0 only, since domU interface
has been stable since 3.0.

Ian.

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Oldest supported Xen version in upstream QEMU (Was: Re: [Minios-devel] [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries)
  2015-09-23  8:29     ` Ian Campbell
  2015-09-23 14:09       ` Konrad Rzeszutek Wilk
@ 2015-09-23 17:36       ` Stefano Stabellini
  2015-09-24  7:15         ` Ian Campbell
  1 sibling, 1 reply; 55+ messages in thread
From: Stefano Stabellini @ 2015-09-23 17:36 UTC (permalink / raw)
  To: Ian Campbell
  Cc: Ian Jackson, xen-devel, Wei Liu, Roger Pau Monne, Stefano Stabellini

On Wed, 23 Sep 2015, Ian Campbell wrote:
> On Tue, 2015-09-22 at 22:31 +0100, Stefano Stabellini wrote: 
> > The oldest Xen version I build-test for every pull request is Xen 4.0.0,
> > I think it is very reasonable to remove anything older than that.
> > I am OK with removing Xen 4.0.0 too, but I would like a warning to be
> > sent ahead of time to qemu-devel to see if anybody complains.
> 
> There is not much point in removing <=3.4 support and keeping 4.0, since
> 4.0.0 was the last one which used a plain int as a handle, anything older
> than 4.0.0 is trivial if 4.0.0 is supported.
> 
> One approach I am considering in order to keep 4.0.0 support and earlier
> was to turn the "int fd" for <=4.0 into a pointer by having the open
> wrapper do malloc(sizeof int) and the using wrappers do xc_foo(*handle).
> 
> This way all the different variants take pointers and we have less hoops to
> jump through to typedef everything in the correct way for each variant.
> 
> If you would rather avoid doing that then I think dropping 4.0.0 support
> would be the way to go and I'll send a mail to qemu-devel.
 
I would rather drop 4.0 support.

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Oldest supported Xen version in upstream QEMU (Was: Re: [Minios-devel] [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries)
  2015-09-23 17:36       ` Stefano Stabellini
@ 2015-09-24  7:15         ` Ian Campbell
  2015-09-24  9:03           ` Fabio Fantoni
  2015-09-24 19:33           ` Stefano Stabellini
  0 siblings, 2 replies; 55+ messages in thread
From: Ian Campbell @ 2015-09-24  7:15 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: Ian Jackson, Roger Pau Monne, Wei Liu, xen-devel

On Wed, 2015-09-23 at 18:36 +0100, Stefano Stabellini wrote:
> On Wed, 23 Sep 2015, Ian Campbell wrote:
> > On Tue, 2015-09-22 at 22:31 +0100, Stefano Stabellini wrote: 
> > > The oldest Xen version I build-test for every pull request is Xen 4.0.0,

I setup a build trees for 4.0 thru 4.6 yesterday to test this, what a
pain 4.1 and 4.0 are to build with a modern gcc! (Mostly newer compiler
warnings and mostly, but not all, fixes which I could just backport
from newer Xen, the exceptions were a couple of things which were
removed before they needed to be fixed)

> > > I think it is very reasonable to remove anything older than that.
> > > I am OK with removing Xen 4.0.0 too, but I would like a warning to be
> > > sent ahead of time to qemu-devel to see if anybody complains.
> > 
> > There is not much point in removing <=3.4 support and keeping 4.0, since
> > 4.0.0 was the last one which used a plain int as a handle, anything older
> > than 4.0.0 is trivial if 4.0.0 is supported.
> > 
> > One approach I am considering in order to keep 4.0.0 support and earlier
> > was to turn the "int fd" for <=4.0 into a pointer by having the open
> > wrapper do malloc(sizeof int) and the using wrappers do xc_foo(*handle).
> > 
> > This way all the different variants take pointers and we have less hoops to
> > jump through to typedef everything in the correct way for each variant.
> > 
> > If you would rather avoid doing that then I think dropping 4.0.0 support
> > would be the way to go and I'll send a mail to qemu-devel.
>  
> I would rather drop 4.0 support.

Supporting 4.0 didn't turn out quite as ugly as I had feared.

So before I send an email to qemu-devel to propose dropping 4.0 what do
you think of the following which handles the evtchn case, there is a
similar patch for gnttab and a (yet to be written) patch for the
foreign memory mapping case.

The relevant bit for this discussion is the 4.0.0 definition of
xenevtchn_open in xen_common.h, the rest is just adjusting it to use
the API of the new library (for reasons explained in the commit
message).

commit d97f6bb5045685d766d85b8cd004ce007fe29120
Author: Ian Campbell <ian.campbell@citrix.com>
Date:   Wed Sep 23 17:30:15 2015 +0100

    xen: Switch to libxenevtchn interface for compat shims.
    
    In Xen 4.7 we are refactoring parts libxenctrl into a number of
    separate libraries which will provide backward and forward API and ABI
    compatiblity.
    
    One such library will be libxenevtchn which provides access to event
    channels.
    
    In preparation for this switch the compatibility layer in xen_common.h
    (which support building with older versions of Xen) to use what will
    be the new library API. This means that the evtchn shim will disappear
    for versions of Xen which include libxenevtchn.
    
    To simplify things for the <= 4.0.0 support we wrap the int fd in a
    malloc(sizeof int) such that the handle is always a pointer. This
    leads to less typedef headaches and the need for
    XC_HANDLER_INITIAL_VALUE etc for these interfaces.
    
    Build tested with 4.1 and 4.5.
    
    Note that this patch does not add any support for actually using
    libxenevtchn, it just adjusts the existing shims.
    
    Note that xc_evtchn_alloc_unbound functionality remains in libxenctrl,
    since that functionality is not exposed by /dev/xen/evtchn.
    
    Signed-off-by: Ian Campbell <ian.campbell@citrix.com>

diff --git a/hw/xen/xen_backend.c b/hw/xen/xen_backend.c
index b2cb22b..1fd8e01 100644
--- a/hw/xen/xen_backend.c
+++ b/hw/xen/xen_backend.c
@@ -243,19 +243,19 @@ static struct XenDevice *xen_be_get_xendev(const char *type, int dom, int dev,
     xendev->debug      = debug;
     xendev->local_port = -1;
 
-    xendev->evtchndev = xen_xc_evtchn_open(NULL, 0);
-    if (xendev->evtchndev == XC_HANDLER_INITIAL_VALUE) {
+    xendev->evtchndev = xenevtchn_open(NULL, 0);
+    if (xendev->evtchndev == NULL) {
         xen_be_printf(NULL, 0, "can't open evtchn device\n");
         g_free(xendev);
         return NULL;
     }
-    fcntl(xc_evtchn_fd(xendev->evtchndev), F_SETFD, FD_CLOEXEC);
+    fcntl(xenevtchn_fd(xendev->evtchndev), F_SETFD, FD_CLOEXEC);
 
     if (ops->flags & DEVOPS_FLAG_NEED_GNTDEV) {
         xendev->gnttabdev = xen_xc_gnttab_open(NULL, 0);
         if (xendev->gnttabdev == XC_HANDLER_INITIAL_VALUE) {
             xen_be_printf(NULL, 0, "can't open gnttab device\n");
-            xc_evtchn_close(xendev->evtchndev);
+            xenevtchn_close(xendev->evtchndev);
             g_free(xendev);
             return NULL;
         }
@@ -306,8 +306,8 @@ static struct XenDevice *xen_be_del_xendev(int dom, int dev)
             g_free(xendev->fe);
         }
 
-        if (xendev->evtchndev != XC_HANDLER_INITIAL_VALUE) {
-            xc_evtchn_close(xendev->evtchndev);
+        if (xendev->evtchndev != NULL) {
+            xenevtchn_close(xendev->evtchndev);
         }
         if (xendev->gnttabdev != XC_HANDLER_INITIAL_VALUE) {
             xc_gnttab_close(xendev->gnttabdev);
@@ -691,13 +691,13 @@ static void xen_be_evtchn_event(void *opaque)
     struct XenDevice *xendev = opaque;
     evtchn_port_t port;
 
-    port = xc_evtchn_pending(xendev->evtchndev);
+    port = xenevtchn_pending(xendev->evtchndev);
     if (port != xendev->local_port) {
-        xen_be_printf(xendev, 0, "xc_evtchn_pending returned %d (expected %d)\n",
+        xen_be_printf(xendev, 0, "xenevtchn_pending returned %d (expected %d)\n",
                       port, xendev->local_port);
         return;
     }
-    xc_evtchn_unmask(xendev->evtchndev, port);
+    xenevtchn_unmask(xendev->evtchndev, port);
 
     if (xendev->ops->event) {
         xendev->ops->event(xendev);
@@ -742,14 +742,14 @@ int xen_be_bind_evtchn(struct XenDevice *xendev)
     if (xendev->local_port != -1) {
         return 0;
     }
-    xendev->local_port = xc_evtchn_bind_interdomain
+    xendev->local_port = xenevtchn_bind_interdomain
         (xendev->evtchndev, xendev->dom, xendev->remote_port);
     if (xendev->local_port == -1) {
-        xen_be_printf(xendev, 0, "xc_evtchn_bind_interdomain failed\n");
+        xen_be_printf(xendev, 0, "xenevtchn_bind_interdomain failed\n");
         return -1;
     }
     xen_be_printf(xendev, 2, "bind evtchn port %d\n", xendev->local_port);
-    qemu_set_fd_handler(xc_evtchn_fd(xendev->evtchndev),
+    qemu_set_fd_handler(xenevtchn_fd(xendev->evtchndev),
                         xen_be_evtchn_event, NULL, xendev);
     return 0;
 }
@@ -759,15 +759,15 @@ void xen_be_unbind_evtchn(struct XenDevice *xendev)
     if (xendev->local_port == -1) {
         return;
     }
-    qemu_set_fd_handler(xc_evtchn_fd(xendev->evtchndev), NULL, NULL, NULL);
-    xc_evtchn_unbind(xendev->evtchndev, xendev->local_port);
+    qemu_set_fd_handler(xenevtchn_fd(xendev->evtchndev), NULL, NULL, NULL);
+    xenevtchn_unbind(xendev->evtchndev, xendev->local_port);
     xen_be_printf(xendev, 2, "unbind evtchn port %d\n", xendev->local_port);
     xendev->local_port = -1;
 }
 
 int xen_be_send_notify(struct XenDevice *xendev)
 {
-    return xc_evtchn_notify(xendev->evtchndev, xendev->local_port);
+    return xenevtchn_notify(xendev->evtchndev, xendev->local_port);
 }
 
 /*
diff --git a/include/hw/xen/xen_backend.h b/include/hw/xen/xen_backend.h
index 3b4125e..a90314f 100644
--- a/include/hw/xen/xen_backend.h
+++ b/include/hw/xen/xen_backend.h
@@ -46,7 +46,7 @@ struct XenDevice {
     int                remote_port;
     int                local_port;
 
-    XenEvtchn          evtchndev;
+    xenevtchn_handle   *evtchndev;
     XenGnttab          gnttabdev;
 
     struct XenDevOps   *ops;
diff --git a/include/hw/xen/xen_common.h b/include/hw/xen/xen_common.h
index 5923290..5700c1b 100644
--- a/include/hw/xen/xen_common.h
+++ b/include/hw/xen/xen_common.h
@@ -39,17 +39,37 @@ static inline void *xc_map_foreign_bulk(int xc_handle, uint32_t dom, int prot,
 #if CONFIG_XEN_CTRL_INTERFACE_VERSION < 410
 
 typedef int XenXC;
-typedef int XenEvtchn;
+typedef int xenevtchn_handle;
 typedef int XenGnttab;
 
 #  define XC_INTERFACE_FMT "%i"
 #  define XC_HANDLER_INITIAL_VALUE    -1
 
-static inline XenEvtchn xen_xc_evtchn_open(void *logger,
-                                           unsigned int open_flags)
+static inline xenevtchn_handle *xenevtchn_open(void *logger,
+					       unsigned int open_flags)
+{
+    int *h = malloc(sizeof h);
+    if (!h)
+	return NULL;
+    *h = xc_evtchn_open();
+    if (*h == -1) {
+	 free(h);
+         h = NULL;
+    }
+    return h;
+}
+static inline int xenevtchn_close(xenevtchn_handle *h)
 {
-    return xc_evtchn_open();
+    int rc = xc_evtchn_close(*h);
+    free(h);
+    return rc;
 }
+#define xenevtchn_fd(h) xc_evtchn_fd(*h)
+#define xenevtchn_pending(h) xc_evtchn_pending(*h)
+#define xenevtchn_notify(h,p) xc_evtchn_notify(*h,p)
+#define xenevtchn_bind_interdomain(h,d,p) xc_evtchn_bind_interdomain(*h,d,p)
+#define xenevtchn_unmask(h,p) xc_evtchn_unmask(*h,p)
+#define xenevtchn_unbind(h,p) xc_evtchn_unmask(*h,p)
 
 static inline XenGnttab xen_xc_gnttab_open(void *logger,
                                            unsigned int open_flags)
@@ -108,17 +128,20 @@ static inline void xs_close(struct xs_handle *xsh)
 #else
 
 typedef xc_interface *XenXC;
-typedef xc_evtchn *XenEvtchn;
+typedef xc_evtchn xenevtchn_handle;
 typedef xc_gnttab *XenGnttab;
 
 #  define XC_INTERFACE_FMT "%p"
 #  define XC_HANDLER_INITIAL_VALUE    NULL
 
-static inline XenEvtchn xen_xc_evtchn_open(void *logger,
-                                           unsigned int open_flags)
-{
-    return xc_evtchn_open(logger, open_flags);
-}
+#define xenevtchn_open(l,f) xc_evtchn_open(l,f);
+#define xenevtchn_close(h) xc_evtchn_close(h)
+#define xenevtchn_fd(h) xc_evtchn_fd(h)
+#define xenevtchn_pending(h) xc_evtchn_pending(h)
+#define xenevtchn_notify(h,p) xc_evtchn_notify(h,p)
+#define xenevtchn_bind_interdomain(h,d,p) xc_evtchn_bind_interdomain(h,d,p)
+#define xenevtchn_unmask(h,p) xc_evtchn_unmask(h,p)
+#define xenevtchn_unbind(h,p) xc_evtchn_unbind(h,p)
 
 static inline XenGnttab xen_xc_gnttab_open(void *logger,
                                            unsigned int open_flags)
diff --git a/xen-hvm.c b/xen-hvm.c
index 3a7fd58..54cbd72 100644
--- a/xen-hvm.c
+++ b/xen-hvm.c
@@ -109,7 +109,7 @@ typedef struct XenIOState {
     /* evtchn local port for buffered io */
     evtchn_port_t bufioreq_local_port;
     /* the evtchn fd for polling */
-    XenEvtchn xce_handle;
+    xenevtchn_handle *xce_handle;
     /* which vcpu we are serving */
     int send_vcpu;
 
@@ -709,7 +709,7 @@ static ioreq_t *cpu_get_ioreq(XenIOState *state)
     int i;
     evtchn_port_t port;
 
-    port = xc_evtchn_pending(state->xce_handle);
+    port = xenevtchn_pending(state->xce_handle);
     if (port == state->bufioreq_local_port) {
         timer_mod(state->buffered_io_timer,
                 BUFFER_IO_MAX_DELAY + qemu_clock_get_ms(QEMU_CLOCK_REALTIME));
@@ -728,7 +728,7 @@ static ioreq_t *cpu_get_ioreq(XenIOState *state)
         }
 
         /* unmask the wanted port again */
-        xc_evtchn_unmask(state->xce_handle, port);
+        xenevtchn_unmask(state->xce_handle, port);
 
         /* get the io packet from shared memory */
         state->send_vcpu = i;
@@ -1014,7 +1014,7 @@ static void handle_buffered_io(void *opaque)
                 BUFFER_IO_MAX_DELAY + qemu_clock_get_ms(QEMU_CLOCK_REALTIME));
     } else {
         timer_del(state->buffered_io_timer);
-        xc_evtchn_unmask(state->xce_handle, state->bufioreq_local_port);
+        xenevtchn_unmask(state->xce_handle, state->bufioreq_local_port);
     }
 }
 
@@ -1058,7 +1058,7 @@ static void cpu_handle_ioreq(void *opaque)
         }
 
         req->state = STATE_IORESP_READY;
-        xc_evtchn_notify(state->xce_handle, state->ioreq_local_port[state->send_vcpu]);
+        xenevtchn_notify(state->xce_handle, state->ioreq_local_port[state->send_vcpu]);
     }
 }
 
@@ -1066,8 +1066,8 @@ static void xen_main_loop_prepare(XenIOState *state)
 {
     int evtchn_fd = -1;
 
-    if (state->xce_handle != XC_HANDLER_INITIAL_VALUE) {
-        evtchn_fd = xc_evtchn_fd(state->xce_handle);
+    if (state->xce_handle != NULL) {
+        evtchn_fd = xenevtchn_fd(state->xce_handle);
     }
 
     state->buffered_io_timer = timer_new_ms(QEMU_CLOCK_REALTIME, handle_buffered_io,
@@ -1105,7 +1105,7 @@ static void xen_exit_notifier(Notifier *n, void *data)
 {
     XenIOState *state = container_of(n, XenIOState, exit);
 
-    xc_evtchn_close(state->xce_handle);
+    xenevtchn_close(state->xce_handle);
     xs_daemon_close(state->xenstore);
 }
 
@@ -1174,8 +1174,8 @@ int xen_hvm_init(ram_addr_t *below_4g_mem_size, ram_addr_t *above_4g_mem_size,
 
     state = g_malloc0(sizeof (XenIOState));
 
-    state->xce_handle = xen_xc_evtchn_open(NULL, 0);
-    if (state->xce_handle == XC_HANDLER_INITIAL_VALUE) {
+    state->xce_handle = xenevtchn_open(NULL, 0);
+    if (state->xce_handle == NULL) {
         perror("xen: event channel open");
         return -1;
     }
@@ -1255,7 +1255,7 @@ int xen_hvm_init(ram_addr_t *below_4g_mem_size, ram_addr_t *above_4g_mem_size,
 
     /* FIXME: how about if we overflow the page here? */
     for (i = 0; i < max_cpus; i++) {
-        rc = xc_evtchn_bind_interdomain(state->xce_handle, xen_domid,
+        rc = xenevtchn_bind_interdomain(state->xce_handle, xen_domid,
                                         xen_vcpu_eport(state->shared_page, i));
         if (rc == -1) {
             fprintf(stderr, "shared evtchn %d bind error %d\n", i, errno);
@@ -1264,7 +1264,7 @@ int xen_hvm_init(ram_addr_t *below_4g_mem_size, ram_addr_t *above_4g_mem_size,
         state->ioreq_local_port[i] = rc;
     }
 
-    rc = xc_evtchn_bind_interdomain(state->xce_handle, xen_domid,
+    rc = xenevtchn_bind_interdomain(state->xce_handle, xen_domid,
                                     bufioreq_evtchn);
     if (rc == -1) {
         fprintf(stderr, "buffered evtchn bind error %d\n", errno);

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* Re: Oldest supported Xen version in upstream QEMU (Was: Re: [Minios-devel] [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries)
  2015-09-24  7:15         ` Ian Campbell
@ 2015-09-24  9:03           ` Fabio Fantoni
  2015-09-24 19:33           ` Stefano Stabellini
  1 sibling, 0 replies; 55+ messages in thread
From: Fabio Fantoni @ 2015-09-24  9:03 UTC (permalink / raw)
  To: Ian Campbell, Stefano Stabellini
  Cc: Wei Liu, xen-devel, Ian Jackson, Roger Pau Monne

Il 24/09/2015 09:15, Ian Campbell ha scritto:
> On Wed, 2015-09-23 at 18:36 +0100, Stefano Stabellini wrote:
>> On Wed, 23 Sep 2015, Ian Campbell wrote:
>>> On Tue, 2015-09-22 at 22:31 +0100, Stefano Stabellini wrote:
>>>> The oldest Xen version I build-test for every pull request is Xen 4.0.0,
> I setup a build trees for 4.0 thru 4.6 yesterday to test this, what a
> pain 4.1 and 4.0 are to build with a modern gcc! (Mostly newer compiler
> warnings and mostly, but not all, fixes which I could just backport
> from newer Xen, the exceptions were a couple of things which were
> removed before they needed to be fixed)
>
>>>> I think it is very reasonable to remove anything older than that.
>>>> I am OK with removing Xen 4.0.0 too, but I would like a warning to be
>>>> sent ahead of time to qemu-devel to see if anybody complains.
>>> There is not much point in removing <=3.4 support and keeping 4.0, since
>>> 4.0.0 was the last one which used a plain int as a handle, anything older
>>> than 4.0.0 is trivial if 4.0.0 is supported.
>>>
>>> One approach I am considering in order to keep 4.0.0 support and earlier
>>> was to turn the "int fd" for <=4.0 into a pointer by having the open
>>> wrapper do malloc(sizeof int) and the using wrappers do xc_foo(*handle).
>>>
>>> This way all the different variants take pointers and we have less hoops to
>>> jump through to typedef everything in the correct way for each variant.
>>>
>>> If you would rather avoid doing that then I think dropping 4.0.0 support
>>> would be the way to go and I'll send a mail to qemu-devel.
>>   
>> I would rather drop 4.0 support.
> Supporting 4.0 didn't turn out quite as ugly as I had feared.

Even if seems that major of distro use newer qemu version instead older 
with xen seems that keep updated also xen to latest stable version (or 
at least previous) and the cases where can uses next qemu version with 
very old xen I think is at least very rare.
Another thing is that upstream qemu on older xen not had good support 
(at least for hvm domUs) and when I started to use it some years ago 
seems that was with too very few users.
There are also some problem, for example this:
http://xenbits.xen.org/gitweb/?p=xen.git;a=commitdiff;h=2e814a017155b885e4d4b5a88dc05e7367a9722a
without hvm domUs with emulated vga don't start with qemu>=1.4, applied 
to xen 4.3 and backported only in stable-4.2
Therefore excluded recent unexpected that I not know for a working 
support of hvm domUsat least xen 4.2 is needed.
In my cases I had saw good hvm domUs support with upstream qemu for 
production use only starting from xen 4.3.
I think is good know if older xen is really used with newer (more 
exactly next for these changes) qemu instead wasting time supporting and 
testing also many older xen versions.
In any cases thanks to all for any xen and qemu improvements.

Sorry for my bad english.

>
> So before I send an email to qemu-devel to propose dropping 4.0 what do
> you think of the following which handles the evtchn case, there is a
> similar patch for gnttab and a (yet to be written) patch for the
> foreign memory mapping case.
>
> The relevant bit for this discussion is the 4.0.0 definition of
> xenevtchn_open in xen_common.h, the rest is just adjusting it to use
> the API of the new library (for reasons explained in the commit
> message).
>
> commit d97f6bb5045685d766d85b8cd004ce007fe29120
> Author: Ian Campbell <ian.campbell@citrix.com>
> Date:   Wed Sep 23 17:30:15 2015 +0100
>
>      xen: Switch to libxenevtchn interface for compat shims.
>      
>      In Xen 4.7 we are refactoring parts libxenctrl into a number of
>      separate libraries which will provide backward and forward API and ABI
>      compatiblity.
>      
>      One such library will be libxenevtchn which provides access to event
>      channels.
>      
>      In preparation for this switch the compatibility layer in xen_common.h
>      (which support building with older versions of Xen) to use what will
>      be the new library API. This means that the evtchn shim will disappear
>      for versions of Xen which include libxenevtchn.
>      
>      To simplify things for the <= 4.0.0 support we wrap the int fd in a
>      malloc(sizeof int) such that the handle is always a pointer. This
>      leads to less typedef headaches and the need for
>      XC_HANDLER_INITIAL_VALUE etc for these interfaces.
>      
>      Build tested with 4.1 and 4.5.
>      
>      Note that this patch does not add any support for actually using
>      libxenevtchn, it just adjusts the existing shims.
>      
>      Note that xc_evtchn_alloc_unbound functionality remains in libxenctrl,
>      since that functionality is not exposed by /dev/xen/evtchn.
>      
>      Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
>
> diff --git a/hw/xen/xen_backend.c b/hw/xen/xen_backend.c
> index b2cb22b..1fd8e01 100644
> --- a/hw/xen/xen_backend.c
> +++ b/hw/xen/xen_backend.c
> @@ -243,19 +243,19 @@ static struct XenDevice *xen_be_get_xendev(const char *type, int dom, int dev,
>       xendev->debug      = debug;
>       xendev->local_port = -1;
>   
> -    xendev->evtchndev = xen_xc_evtchn_open(NULL, 0);
> -    if (xendev->evtchndev == XC_HANDLER_INITIAL_VALUE) {
> +    xendev->evtchndev = xenevtchn_open(NULL, 0);
> +    if (xendev->evtchndev == NULL) {
>           xen_be_printf(NULL, 0, "can't open evtchn device\n");
>           g_free(xendev);
>           return NULL;
>       }
> -    fcntl(xc_evtchn_fd(xendev->evtchndev), F_SETFD, FD_CLOEXEC);
> +    fcntl(xenevtchn_fd(xendev->evtchndev), F_SETFD, FD_CLOEXEC);
>   
>       if (ops->flags & DEVOPS_FLAG_NEED_GNTDEV) {
>           xendev->gnttabdev = xen_xc_gnttab_open(NULL, 0);
>           if (xendev->gnttabdev == XC_HANDLER_INITIAL_VALUE) {
>               xen_be_printf(NULL, 0, "can't open gnttab device\n");
> -            xc_evtchn_close(xendev->evtchndev);
> +            xenevtchn_close(xendev->evtchndev);
>               g_free(xendev);
>               return NULL;
>           }
> @@ -306,8 +306,8 @@ static struct XenDevice *xen_be_del_xendev(int dom, int dev)
>               g_free(xendev->fe);
>           }
>   
> -        if (xendev->evtchndev != XC_HANDLER_INITIAL_VALUE) {
> -            xc_evtchn_close(xendev->evtchndev);
> +        if (xendev->evtchndev != NULL) {
> +            xenevtchn_close(xendev->evtchndev);
>           }
>           if (xendev->gnttabdev != XC_HANDLER_INITIAL_VALUE) {
>               xc_gnttab_close(xendev->gnttabdev);
> @@ -691,13 +691,13 @@ static void xen_be_evtchn_event(void *opaque)
>       struct XenDevice *xendev = opaque;
>       evtchn_port_t port;
>   
> -    port = xc_evtchn_pending(xendev->evtchndev);
> +    port = xenevtchn_pending(xendev->evtchndev);
>       if (port != xendev->local_port) {
> -        xen_be_printf(xendev, 0, "xc_evtchn_pending returned %d (expected %d)\n",
> +        xen_be_printf(xendev, 0, "xenevtchn_pending returned %d (expected %d)\n",
>                         port, xendev->local_port);
>           return;
>       }
> -    xc_evtchn_unmask(xendev->evtchndev, port);
> +    xenevtchn_unmask(xendev->evtchndev, port);
>   
>       if (xendev->ops->event) {
>           xendev->ops->event(xendev);
> @@ -742,14 +742,14 @@ int xen_be_bind_evtchn(struct XenDevice *xendev)
>       if (xendev->local_port != -1) {
>           return 0;
>       }
> -    xendev->local_port = xc_evtchn_bind_interdomain
> +    xendev->local_port = xenevtchn_bind_interdomain
>           (xendev->evtchndev, xendev->dom, xendev->remote_port);
>       if (xendev->local_port == -1) {
> -        xen_be_printf(xendev, 0, "xc_evtchn_bind_interdomain failed\n");
> +        xen_be_printf(xendev, 0, "xenevtchn_bind_interdomain failed\n");
>           return -1;
>       }
>       xen_be_printf(xendev, 2, "bind evtchn port %d\n", xendev->local_port);
> -    qemu_set_fd_handler(xc_evtchn_fd(xendev->evtchndev),
> +    qemu_set_fd_handler(xenevtchn_fd(xendev->evtchndev),
>                           xen_be_evtchn_event, NULL, xendev);
>       return 0;
>   }
> @@ -759,15 +759,15 @@ void xen_be_unbind_evtchn(struct XenDevice *xendev)
>       if (xendev->local_port == -1) {
>           return;
>       }
> -    qemu_set_fd_handler(xc_evtchn_fd(xendev->evtchndev), NULL, NULL, NULL);
> -    xc_evtchn_unbind(xendev->evtchndev, xendev->local_port);
> +    qemu_set_fd_handler(xenevtchn_fd(xendev->evtchndev), NULL, NULL, NULL);
> +    xenevtchn_unbind(xendev->evtchndev, xendev->local_port);
>       xen_be_printf(xendev, 2, "unbind evtchn port %d\n", xendev->local_port);
>       xendev->local_port = -1;
>   }
>   
>   int xen_be_send_notify(struct XenDevice *xendev)
>   {
> -    return xc_evtchn_notify(xendev->evtchndev, xendev->local_port);
> +    return xenevtchn_notify(xendev->evtchndev, xendev->local_port);
>   }
>   
>   /*
> diff --git a/include/hw/xen/xen_backend.h b/include/hw/xen/xen_backend.h
> index 3b4125e..a90314f 100644
> --- a/include/hw/xen/xen_backend.h
> +++ b/include/hw/xen/xen_backend.h
> @@ -46,7 +46,7 @@ struct XenDevice {
>       int                remote_port;
>       int                local_port;
>   
> -    XenEvtchn          evtchndev;
> +    xenevtchn_handle   *evtchndev;
>       XenGnttab          gnttabdev;
>   
>       struct XenDevOps   *ops;
> diff --git a/include/hw/xen/xen_common.h b/include/hw/xen/xen_common.h
> index 5923290..5700c1b 100644
> --- a/include/hw/xen/xen_common.h
> +++ b/include/hw/xen/xen_common.h
> @@ -39,17 +39,37 @@ static inline void *xc_map_foreign_bulk(int xc_handle, uint32_t dom, int prot,
>   #if CONFIG_XEN_CTRL_INTERFACE_VERSION < 410
>   
>   typedef int XenXC;
> -typedef int XenEvtchn;
> +typedef int xenevtchn_handle;
>   typedef int XenGnttab;
>   
>   #  define XC_INTERFACE_FMT "%i"
>   #  define XC_HANDLER_INITIAL_VALUE    -1
>   
> -static inline XenEvtchn xen_xc_evtchn_open(void *logger,
> -                                           unsigned int open_flags)
> +static inline xenevtchn_handle *xenevtchn_open(void *logger,
> +					       unsigned int open_flags)
> +{
> +    int *h = malloc(sizeof h);
> +    if (!h)
> +	return NULL;
> +    *h = xc_evtchn_open();
> +    if (*h == -1) {
> +	 free(h);
> +         h = NULL;
> +    }
> +    return h;
> +}
> +static inline int xenevtchn_close(xenevtchn_handle *h)
>   {
> -    return xc_evtchn_open();
> +    int rc = xc_evtchn_close(*h);
> +    free(h);
> +    return rc;
>   }
> +#define xenevtchn_fd(h) xc_evtchn_fd(*h)
> +#define xenevtchn_pending(h) xc_evtchn_pending(*h)
> +#define xenevtchn_notify(h,p) xc_evtchn_notify(*h,p)
> +#define xenevtchn_bind_interdomain(h,d,p) xc_evtchn_bind_interdomain(*h,d,p)
> +#define xenevtchn_unmask(h,p) xc_evtchn_unmask(*h,p)
> +#define xenevtchn_unbind(h,p) xc_evtchn_unmask(*h,p)
>   
>   static inline XenGnttab xen_xc_gnttab_open(void *logger,
>                                              unsigned int open_flags)
> @@ -108,17 +128,20 @@ static inline void xs_close(struct xs_handle *xsh)
>   #else
>   
>   typedef xc_interface *XenXC;
> -typedef xc_evtchn *XenEvtchn;
> +typedef xc_evtchn xenevtchn_handle;
>   typedef xc_gnttab *XenGnttab;
>   
>   #  define XC_INTERFACE_FMT "%p"
>   #  define XC_HANDLER_INITIAL_VALUE    NULL
>   
> -static inline XenEvtchn xen_xc_evtchn_open(void *logger,
> -                                           unsigned int open_flags)
> -{
> -    return xc_evtchn_open(logger, open_flags);
> -}
> +#define xenevtchn_open(l,f) xc_evtchn_open(l,f);
> +#define xenevtchn_close(h) xc_evtchn_close(h)
> +#define xenevtchn_fd(h) xc_evtchn_fd(h)
> +#define xenevtchn_pending(h) xc_evtchn_pending(h)
> +#define xenevtchn_notify(h,p) xc_evtchn_notify(h,p)
> +#define xenevtchn_bind_interdomain(h,d,p) xc_evtchn_bind_interdomain(h,d,p)
> +#define xenevtchn_unmask(h,p) xc_evtchn_unmask(h,p)
> +#define xenevtchn_unbind(h,p) xc_evtchn_unbind(h,p)
>   
>   static inline XenGnttab xen_xc_gnttab_open(void *logger,
>                                              unsigned int open_flags)
> diff --git a/xen-hvm.c b/xen-hvm.c
> index 3a7fd58..54cbd72 100644
> --- a/xen-hvm.c
> +++ b/xen-hvm.c
> @@ -109,7 +109,7 @@ typedef struct XenIOState {
>       /* evtchn local port for buffered io */
>       evtchn_port_t bufioreq_local_port;
>       /* the evtchn fd for polling */
> -    XenEvtchn xce_handle;
> +    xenevtchn_handle *xce_handle;
>       /* which vcpu we are serving */
>       int send_vcpu;
>   
> @@ -709,7 +709,7 @@ static ioreq_t *cpu_get_ioreq(XenIOState *state)
>       int i;
>       evtchn_port_t port;
>   
> -    port = xc_evtchn_pending(state->xce_handle);
> +    port = xenevtchn_pending(state->xce_handle);
>       if (port == state->bufioreq_local_port) {
>           timer_mod(state->buffered_io_timer,
>                   BUFFER_IO_MAX_DELAY + qemu_clock_get_ms(QEMU_CLOCK_REALTIME));
> @@ -728,7 +728,7 @@ static ioreq_t *cpu_get_ioreq(XenIOState *state)
>           }
>   
>           /* unmask the wanted port again */
> -        xc_evtchn_unmask(state->xce_handle, port);
> +        xenevtchn_unmask(state->xce_handle, port);
>   
>           /* get the io packet from shared memory */
>           state->send_vcpu = i;
> @@ -1014,7 +1014,7 @@ static void handle_buffered_io(void *opaque)
>                   BUFFER_IO_MAX_DELAY + qemu_clock_get_ms(QEMU_CLOCK_REALTIME));
>       } else {
>           timer_del(state->buffered_io_timer);
> -        xc_evtchn_unmask(state->xce_handle, state->bufioreq_local_port);
> +        xenevtchn_unmask(state->xce_handle, state->bufioreq_local_port);
>       }
>   }
>   
> @@ -1058,7 +1058,7 @@ static void cpu_handle_ioreq(void *opaque)
>           }
>   
>           req->state = STATE_IORESP_READY;
> -        xc_evtchn_notify(state->xce_handle, state->ioreq_local_port[state->send_vcpu]);
> +        xenevtchn_notify(state->xce_handle, state->ioreq_local_port[state->send_vcpu]);
>       }
>   }
>   
> @@ -1066,8 +1066,8 @@ static void xen_main_loop_prepare(XenIOState *state)
>   {
>       int evtchn_fd = -1;
>   
> -    if (state->xce_handle != XC_HANDLER_INITIAL_VALUE) {
> -        evtchn_fd = xc_evtchn_fd(state->xce_handle);
> +    if (state->xce_handle != NULL) {
> +        evtchn_fd = xenevtchn_fd(state->xce_handle);
>       }
>   
>       state->buffered_io_timer = timer_new_ms(QEMU_CLOCK_REALTIME, handle_buffered_io,
> @@ -1105,7 +1105,7 @@ static void xen_exit_notifier(Notifier *n, void *data)
>   {
>       XenIOState *state = container_of(n, XenIOState, exit);
>   
> -    xc_evtchn_close(state->xce_handle);
> +    xenevtchn_close(state->xce_handle);
>       xs_daemon_close(state->xenstore);
>   }
>   
> @@ -1174,8 +1174,8 @@ int xen_hvm_init(ram_addr_t *below_4g_mem_size, ram_addr_t *above_4g_mem_size,
>   
>       state = g_malloc0(sizeof (XenIOState));
>   
> -    state->xce_handle = xen_xc_evtchn_open(NULL, 0);
> -    if (state->xce_handle == XC_HANDLER_INITIAL_VALUE) {
> +    state->xce_handle = xenevtchn_open(NULL, 0);
> +    if (state->xce_handle == NULL) {
>           perror("xen: event channel open");
>           return -1;
>       }
> @@ -1255,7 +1255,7 @@ int xen_hvm_init(ram_addr_t *below_4g_mem_size, ram_addr_t *above_4g_mem_size,
>   
>       /* FIXME: how about if we overflow the page here? */
>       for (i = 0; i < max_cpus; i++) {
> -        rc = xc_evtchn_bind_interdomain(state->xce_handle, xen_domid,
> +        rc = xenevtchn_bind_interdomain(state->xce_handle, xen_domid,
>                                           xen_vcpu_eport(state->shared_page, i));
>           if (rc == -1) {
>               fprintf(stderr, "shared evtchn %d bind error %d\n", i, errno);
> @@ -1264,7 +1264,7 @@ int xen_hvm_init(ram_addr_t *below_4g_mem_size, ram_addr_t *above_4g_mem_size,
>           state->ioreq_local_port[i] = rc;
>       }
>   
> -    rc = xc_evtchn_bind_interdomain(state->xce_handle, xen_domid,
> +    rc = xenevtchn_bind_interdomain(state->xce_handle, xen_domid,
>                                       bufioreq_evtchn);
>       if (rc == -1) {
>           fprintf(stderr, "buffered evtchn bind error %d\n", errno);
>
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xen.org
> http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [Minios-devel] [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries
  2015-07-15 15:46 [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries Ian Campbell
                   ` (26 preceding siblings ...)
  2015-09-22 15:03 ` Oldest supported Xen version in upstream QEMU (Was: Re: [Minios-devel] [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries) Ian Campbell
@ 2015-09-24 16:47 ` Ian Campbell
  27 siblings, 0 replies; 55+ messages in thread
From: Ian Campbell @ 2015-09-24 16:47 UTC (permalink / raw)
  To: xen-devel, David Vrabel; +Cc: Ian Jackson, Wei Liu, Stefano Stabellini

(dropping mini-os-devel and some cc's, adding David)

Hi David,

On Wed, 2015-07-15 at 16:46 +0100, Ian Campbell wrote:
> (this is clearly not 4.6 material, aiming for 4.7)
> 
> In <1431963008.4944.80.camel@citrix.com> I proposed stabilising some
> parts of the libxenctrl API/ABI by disaggregating into separate
> libraries.
> 
[...]
> Still to come would be libraries for specific out of tree purposes
> (device model, kexec),

For kexec I have ("S" column is "interface to the left is stable A(BP)I"):

Interface                          S Underlying Interface           S Other users
---------------------------------- - ------------------------------ - ---------------
`xc__hypercall_buffer_array_alloc`   Should use libxencall
`xc_hypercall_buffer_array_create`   Should use libxencall
`xc_hypercall_buffer_array_des...`   Should use libxencall
`xc_interface_close`
`xc_interface_open`
`xc_get_max_cpus`                  N `xc_physinfo=SYSCTL_physinfo`  N many
`xc_version`                       N `XENVER_capabilities`          Y libxl,others
`xc_get_machine_memory_map`        N `XENMEM_machine_memory_map`    Y libxl

`xc_kexec_exec`                    N `KEXEC_CMD_kexec`              Y None
`xc_kexec_get_range`               N `KEXEC_CMD_kexec_get_range`    Y None
`xc_kexec_load`                    N `KEXEC_CMD_kexec_load`         Y None
`xc_kexec_unload`                  N `KEXEC_CMD_kexec_unload`       Y None

It seems to me that there is not all that much utility to providing a
stable libxenkexec containing those last four, and that they might as well
be moved to kexec-tools where they can be implemented using the new
libxencall (which also includes the buffer allocation stuff for the first
3).

What do you think?

That would just leave xc_get_max_cpus, xc_version and
xc_get_machine_memory_map, which I'm still pondering.

Ian.

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Oldest supported Xen version in upstream QEMU (Was: Re: [Minios-devel] [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries)
  2015-09-24  7:15         ` Ian Campbell
  2015-09-24  9:03           ` Fabio Fantoni
@ 2015-09-24 19:33           ` Stefano Stabellini
  2015-09-24 21:11             ` Ian Campbell
  1 sibling, 1 reply; 55+ messages in thread
From: Stefano Stabellini @ 2015-09-24 19:33 UTC (permalink / raw)
  To: Ian Campbell
  Cc: Ian Jackson, xen-devel, Wei Liu, Roger Pau Monne, Stefano Stabellini

On Thu, 24 Sep 2015, Ian Campbell wrote:
> On Wed, 2015-09-23 at 18:36 +0100, Stefano Stabellini wrote:
> > On Wed, 23 Sep 2015, Ian Campbell wrote:
> > > On Tue, 2015-09-22 at 22:31 +0100, Stefano Stabellini wrote: 
> > > > The oldest Xen version I build-test for every pull request is Xen 4.0.0,
> 
> I setup a build trees for 4.0 thru 4.6 yesterday to test this, what a
> pain 4.1 and 4.0 are to build with a modern gcc! (Mostly newer compiler
> warnings and mostly, but not all, fixes which I could just backport
> from newer Xen, the exceptions were a couple of things which were
> removed before they needed to be fixed)
> 
> > > > I think it is very reasonable to remove anything older than that.
> > > > I am OK with removing Xen 4.0.0 too, but I would like a warning to be
> > > > sent ahead of time to qemu-devel to see if anybody complains.
> > > 
> > > There is not much point in removing <=3.4 support and keeping 4.0, since
> > > 4.0.0 was the last one which used a plain int as a handle, anything older
> > > than 4.0.0 is trivial if 4.0.0 is supported.
> > > 
> > > One approach I am considering in order to keep 4.0.0 support and earlier
> > > was to turn the "int fd" for <=4.0 into a pointer by having the open
> > > wrapper do malloc(sizeof int) and the using wrappers do xc_foo(*handle).
> > > 
> > > This way all the different variants take pointers and we have less hoops to
> > > jump through to typedef everything in the correct way for each variant.
> > > 
> > > If you would rather avoid doing that then I think dropping 4.0.0 support
> > > would be the way to go and I'll send a mail to qemu-devel.
> >  
> > I would rather drop 4.0 support.
> 
> Supporting 4.0 didn't turn out quite as ugly as I had feared.
> 
> So before I send an email to qemu-devel to propose dropping 4.0 what do
> you think of the following which handles the evtchn case, there is a
> similar patch for gnttab and a (yet to be written) patch for the
> foreign memory mapping case.
> 
> The relevant bit for this discussion is the 4.0.0 definition of
> xenevtchn_open in xen_common.h, the rest is just adjusting it to use
> the API of the new library (for reasons explained in the commit
> message).

I think that it is OK in principle.


> diff --git a/include/hw/xen/xen_common.h b/include/hw/xen/xen_common.h
> index 5923290..5700c1b 100644
> --- a/include/hw/xen/xen_common.h
> +++ b/include/hw/xen/xen_common.h
> @@ -39,17 +39,37 @@ static inline void *xc_map_foreign_bulk(int xc_handle, uint32_t dom, int prot,
>  #if CONFIG_XEN_CTRL_INTERFACE_VERSION < 410
>  
>  typedef int XenXC;
> -typedef int XenEvtchn;
> +typedef int xenevtchn_handle;
>  typedef int XenGnttab;
 
...

> @@ -108,17 +128,20 @@ static inline void xs_close(struct xs_handle *xsh)
>  #else
>  
>  typedef xc_interface *XenXC;
> -typedef xc_evtchn *XenEvtchn;
> +typedef xc_evtchn xenevtchn_handle;
>  typedef xc_gnttab *XenGnttab;
>  

There is no reasons why we couldn't have a small compat shim on Xen >
4.6 too, so I would change the definition of XenEvtchn for newer
versions of Xen and avoid some of the renaming in this patch to reduce
the changes.

For example, why not define xc_evtchn_fd as xenevtchn_fd for Xen > 4.6?
So that we don't need to go and rename all the call sites?

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Oldest supported Xen version in upstream QEMU (Was: Re: [Minios-devel] [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries)
  2015-09-24 19:33           ` Stefano Stabellini
@ 2015-09-24 21:11             ` Ian Campbell
  2015-09-24 22:19               ` Stefano Stabellini
  0 siblings, 1 reply; 55+ messages in thread
From: Ian Campbell @ 2015-09-24 21:11 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: Ian Jackson, Roger Pau Monne, Wei Liu, xen-devel

On Thu, 2015-09-24 at 20:33 +0100, Stefano Stabellini wrote:
> On Thu, 24 Sep 2015, Ian Campbell wrote:
> > On Wed, 2015-09-23 at 18:36 +0100, Stefano Stabellini wrote:
> > > On Wed, 23 Sep 2015, Ian Campbell wrote:
> > > > On Tue, 2015-09-22 at 22:31 +0100, Stefano Stabellini wrote: 
> > > > > The oldest Xen version I build-test for every pull request is
> Xen 4.0.0,
> > 
> > I setup a build trees for 4.0 thru 4.6 yesterday to test this, what
> a
> > pain 4.1 and 4.0 are to build with a modern gcc! (Mostly newer
> compiler
> > warnings and mostly, but not all, fixes which I could just backport
> > from newer Xen, the exceptions were a couple of things which were
> > removed before they needed to be fixed)
> > 
> > > > > I think it is very reasonable to remove anything older than
> that.
> > > > > I am OK with removing Xen 4.0.0 too, but I would like a
> warning to be
> > > > > sent ahead of time to qemu-devel to see if anybody complains.
> > > > 
> > > > There is not much point in removing <=3.4 support and keeping
> 4.0, since
> > > > 4.0.0 was the last one which used a plain int as a handle,
> anything older
> > > > than 4.0.0 is trivial if 4.0.0 is supported.
> > > > 
> > > > One approach I am considering in order to keep 4.0.0 support
> and earlier
> > > > was to turn the "int fd" for <=4.0 into a pointer by having the
> open
> > > > wrapper do malloc(sizeof int) and the using wrappers do
> xc_foo(*handle).
> > > > 
> > > > This way all the different variants take pointers and we have
> less hoops to
> > > > jump through to typedef everything in the correct way for each
> variant.
> > > > 
> > > > If you would rather avoid doing that then I think dropping
> 4.0.0 support
> > > > would be the way to go and I'll send a mail to qemu-devel.
> > >  
> > > I would rather drop 4.0 support.
> > 
> > Supporting 4.0 didn't turn out quite as ugly as I had feared.
> > 
> > So before I send an email to qemu-devel to propose dropping 4.0
> what do
> > you think of the following which handles the evtchn case, there is
> a
> > similar patch for gnttab and a (yet to be written) patch for the
> > foreign memory mapping case.
> > 
> > The relevant bit for this discussion is the 4.0.0 definition of
> > xenevtchn_open in xen_common.h, the rest is just adjusting it to
> use
> > the API of the new library (for reasons explained in the commit
> > message).
> 
> I think that it is OK in principle.
> 
> 
> > diff --git a/include/hw/xen/xen_common.h
> b/include/hw/xen/xen_common.h
> > index 5923290..5700c1b 100644
> > --- a/include/hw/xen/xen_common.h
> > +++ b/include/hw/xen/xen_common.h
> > @@ -39,17 +39,37 @@ static inline void *xc_map_foreign_bulk(int
> xc_handle, uint32_t dom, int prot,
> >  #if CONFIG_XEN_CTRL_INTERFACE_VERSION < 410
> >  
> >  typedef int XenXC;
> > -typedef int XenEvtchn;
> > +typedef int xenevtchn_handle;
> >  typedef int XenGnttab;
>  
> ...
> 
> > @@ -108,17 +128,20 @@ static inline void xs_close(struct xs_handle
> *xsh)
> >  #else
> >  
> >  typedef xc_interface *XenXC;
> > -typedef xc_evtchn *XenEvtchn;
> > +typedef xc_evtchn xenevtchn_handle;
> >  typedef xc_gnttab *XenGnttab;
> >  
> 
> There is no reasons why we couldn't have a small compat shim on Xen >
> 4.6 too, so I would change the definition of XenEvtchn for newer
> versions of Xen and avoid some of the renaming in this patch to reduce
> the changes.
> 
> For example, why not define xc_evtchn_fd as xenevtchn_fd for Xen > 4.6?
> So that we don't need to go and rename all the call sites?

The idea was that the code would use the new stable API names from the
stable libraries going forward, rather than using a shim to turn the
stable APIs back into the old ones.

Ian.

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Oldest supported Xen version in upstream QEMU (Was: Re: [Minios-devel] [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries)
  2015-09-24 21:11             ` Ian Campbell
@ 2015-09-24 22:19               ` Stefano Stabellini
  2015-09-25  8:27                 ` Ian Campbell
  0 siblings, 1 reply; 55+ messages in thread
From: Stefano Stabellini @ 2015-09-24 22:19 UTC (permalink / raw)
  To: Ian Campbell
  Cc: Ian Jackson, xen-devel, Wei Liu, Roger Pau Monne, Stefano Stabellini

On Thu, 24 Sep 2015, Ian Campbell wrote:
> On Thu, 2015-09-24 at 20:33 +0100, Stefano Stabellini wrote:
> > On Thu, 24 Sep 2015, Ian Campbell wrote:
> > > On Wed, 2015-09-23 at 18:36 +0100, Stefano Stabellini wrote:
> > > > On Wed, 23 Sep 2015, Ian Campbell wrote:
> > > > > On Tue, 2015-09-22 at 22:31 +0100, Stefano Stabellini wrote: 
> > > > > > The oldest Xen version I build-test for every pull request is
> > Xen 4.0.0,
> > > 
> > > I setup a build trees for 4.0 thru 4.6 yesterday to test this, what
> > a
> > > pain 4.1 and 4.0 are to build with a modern gcc! (Mostly newer
> > compiler
> > > warnings and mostly, but not all, fixes which I could just backport
> > > from newer Xen, the exceptions were a couple of things which were
> > > removed before they needed to be fixed)
> > > 
> > > > > > I think it is very reasonable to remove anything older than
> > that.
> > > > > > I am OK with removing Xen 4.0.0 too, but I would like a
> > warning to be
> > > > > > sent ahead of time to qemu-devel to see if anybody complains.
> > > > > 
> > > > > There is not much point in removing <=3.4 support and keeping
> > 4.0, since
> > > > > 4.0.0 was the last one which used a plain int as a handle,
> > anything older
> > > > > than 4.0.0 is trivial if 4.0.0 is supported.
> > > > > 
> > > > > One approach I am considering in order to keep 4.0.0 support
> > and earlier
> > > > > was to turn the "int fd" for <=4.0 into a pointer by having the
> > open
> > > > > wrapper do malloc(sizeof int) and the using wrappers do
> > xc_foo(*handle).
> > > > > 
> > > > > This way all the different variants take pointers and we have
> > less hoops to
> > > > > jump through to typedef everything in the correct way for each
> > variant.
> > > > > 
> > > > > If you would rather avoid doing that then I think dropping
> > 4.0.0 support
> > > > > would be the way to go and I'll send a mail to qemu-devel.
> > > >  
> > > > I would rather drop 4.0 support.
> > > 
> > > Supporting 4.0 didn't turn out quite as ugly as I had feared.
> > > 
> > > So before I send an email to qemu-devel to propose dropping 4.0
> > what do
> > > you think of the following which handles the evtchn case, there is
> > a
> > > similar patch for gnttab and a (yet to be written) patch for the
> > > foreign memory mapping case.
> > > 
> > > The relevant bit for this discussion is the 4.0.0 definition of
> > > xenevtchn_open in xen_common.h, the rest is just adjusting it to
> > use
> > > the API of the new library (for reasons explained in the commit
> > > message).
> > 
> > I think that it is OK in principle.
> > 
> > 
> > > diff --git a/include/hw/xen/xen_common.h
> > b/include/hw/xen/xen_common.h
> > > index 5923290..5700c1b 100644
> > > --- a/include/hw/xen/xen_common.h
> > > +++ b/include/hw/xen/xen_common.h
> > > @@ -39,17 +39,37 @@ static inline void *xc_map_foreign_bulk(int
> > xc_handle, uint32_t dom, int prot,
> > >  #if CONFIG_XEN_CTRL_INTERFACE_VERSION < 410
> > >  
> > >  typedef int XenXC;
> > > -typedef int XenEvtchn;
> > > +typedef int xenevtchn_handle;
> > >  typedef int XenGnttab;
> >  
> > ...
> > 
> > > @@ -108,17 +128,20 @@ static inline void xs_close(struct xs_handle
> > *xsh)
> > >  #else
> > >  
> > >  typedef xc_interface *XenXC;
> > > -typedef xc_evtchn *XenEvtchn;
> > > +typedef xc_evtchn xenevtchn_handle;
> > >  typedef xc_gnttab *XenGnttab;
> > >  
> > 
> > There is no reasons why we couldn't have a small compat shim on Xen >
> > 4.6 too, so I would change the definition of XenEvtchn for newer
> > versions of Xen and avoid some of the renaming in this patch to reduce
> > the changes.
> > 
> > For example, why not define xc_evtchn_fd as xenevtchn_fd for Xen > 4.6?
> > So that we don't need to go and rename all the call sites?
> 
> The idea was that the code would use the new stable API names from the
> stable libraries going forward, rather than using a shim to turn the
> stable APIs back into the old ones.

I don't think that is very important from QEMU's point of view, using a
shim is just fine, especially if it reduces the patch size to 5 lines of
code :-)

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Oldest supported Xen version in upstream QEMU (Was: Re: [Minios-devel] [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries)
  2015-09-24 22:19               ` Stefano Stabellini
@ 2015-09-25  8:27                 ` Ian Campbell
  2015-09-25 20:31                   ` Stefano Stabellini
  0 siblings, 1 reply; 55+ messages in thread
From: Ian Campbell @ 2015-09-25  8:27 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: Ian Jackson, Roger Pau Monne, Wei Liu, xen-devel

On Thu, 2015-09-24 at 23:19 +0100, Stefano Stabellini wrote:
> On Thu, 24 Sep 2015, Ian Campbell wrote:
> > On Thu, 2015-09-24 at 20:33 +0100, Stefano Stabellini wrote:
> > > On Thu, 24 Sep 2015, Ian Campbell wrote:
> > > > On Wed, 2015-09-23 at 18:36 +0100, Stefano Stabellini wrote:
> > > > > On Wed, 23 Sep 2015, Ian Campbell wrote:
> > > > > > On Tue, 2015-09-22 at 22:31 +0100, Stefano Stabellini wrote: 
> > > > > > > The oldest Xen version I build-test for every pull request is
> > > Xen 4.0.0,
> > > > 
> > > > I setup a build trees for 4.0 thru 4.6 yesterday to test this, what
> > > a
> > > > pain 4.1 and 4.0 are to build with a modern gcc! (Mostly newer
> > > compiler
> > > > warnings and mostly, but not all, fixes which I could just backport
> > > > from newer Xen, the exceptions were a couple of things which were
> > > > removed before they needed to be fixed)
> > > > 
> > > > > > > I think it is very reasonable to remove anything older than
> > > that.
> > > > > > > I am OK with removing Xen 4.0.0 too, but I would like a
> > > warning to be
> > > > > > > sent ahead of time to qemu-devel to see if anybody complains.
> > > > > > 
> > > > > > There is not much point in removing <=3.4 support and keeping
> > > 4.0, since
> > > > > > 4.0.0 was the last one which used a plain int as a handle,
> > > anything older
> > > > > > than 4.0.0 is trivial if 4.0.0 is supported.
> > > > > > 
> > > > > > One approach I am considering in order to keep 4.0.0 support
> > > and earlier
> > > > > > was to turn the "int fd" for <=4.0 into a pointer by having the
> > > open
> > > > > > wrapper do malloc(sizeof int) and the using wrappers do
> > > xc_foo(*handle).
> > > > > > 
> > > > > > This way all the different variants take pointers and we have
> > > less hoops to
> > > > > > jump through to typedef everything in the correct way for each
> > > variant.
> > > > > > 
> > > > > > If you would rather avoid doing that then I think dropping
> > > 4.0.0 support
> > > > > > would be the way to go and I'll send a mail to qemu-devel.
> > > > >  
> > > > > I would rather drop 4.0 support.
> > > > 
> > > > Supporting 4.0 didn't turn out quite as ugly as I had feared.
> > > > 
> > > > So before I send an email to qemu-devel to propose dropping 4.0
> > > what do
> > > > you think of the following which handles the evtchn case, there is
> > > a
> > > > similar patch for gnttab and a (yet to be written) patch for the
> > > > foreign memory mapping case.
> > > > 
> > > > The relevant bit for this discussion is the 4.0.0 definition of
> > > > xenevtchn_open in xen_common.h, the rest is just adjusting it to
> > > use
> > > > the API of the new library (for reasons explained in the commit
> > > > message).
> > > 
> > > I think that it is OK in principle.
> > > 
> > > 
> > > > diff --git a/include/hw/xen/xen_common.h
> > > b/include/hw/xen/xen_common.h
> > > > index 5923290..5700c1b 100644
> > > > --- a/include/hw/xen/xen_common.h
> > > > +++ b/include/hw/xen/xen_common.h
> > > > @@ -39,17 +39,37 @@ static inline void *xc_map_foreign_bulk(int
> > > xc_handle, uint32_t dom, int prot,
> > > >  #if CONFIG_XEN_CTRL_INTERFACE_VERSION < 410
> > > >  
> > > >  typedef int XenXC;
> > > > -typedef int XenEvtchn;
> > > > +typedef int xenevtchn_handle;
> > > >  typedef int XenGnttab;
> > >  
> > > ...
> > > 
> > > > @@ -108,17 +128,20 @@ static inline void xs_close(struct xs_handle
> > > *xsh)
> > > >  #else
> > > >  
> > > >  typedef xc_interface *XenXC;
> > > > -typedef xc_evtchn *XenEvtchn;
> > > > +typedef xc_evtchn xenevtchn_handle;
> > > >  typedef xc_gnttab *XenGnttab;
> > > >  
> > > 
> > > There is no reasons why we couldn't have a small compat shim on Xen >
> > > 4.6 too, so I would change the definition of XenEvtchn for newer
> > > versions of Xen and avoid some of the renaming in this patch to
> > > reduce
> > > the changes.
> > > 
> > > For example, why not define xc_evtchn_fd as xenevtchn_fd for Xen >
> > > 4.6?
> > > So that we don't need to go and rename all the call sites?
> > 
> > The idea was that the code would use the new stable API names from the
> > stable libraries going forward, rather than using a shim to turn the
> > stable APIs back into the old ones.
> 
> I don't think that is very important from QEMU's point of view, using a
> shim is just fine, especially if it reduces the patch size to 5 lines of
> code :-)

Is patch size really the major consideration here? IMHO it is simply less
confusing to have no shim (since one doesn't need to translate the names
when reading differing code bases) and with time the shim layers can drop
away leading to less complexity.

Also, I've already written all the patches, the renamings were very
mechanical and at this point it would actually take me longer to undo them.

I'll do that if you insist, but I think the justification for sticking with
a shim is very flimsy.

Ian.

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Oldest supported Xen version in upstream QEMU (Was: Re: [Minios-devel] [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries)
  2015-09-25  8:27                 ` Ian Campbell
@ 2015-09-25 20:31                   ` Stefano Stabellini
  0 siblings, 0 replies; 55+ messages in thread
From: Stefano Stabellini @ 2015-09-25 20:31 UTC (permalink / raw)
  To: Ian Campbell
  Cc: Ian Jackson, xen-devel, Wei Liu, Roger Pau Monne, Stefano Stabellini

On Fri, 25 Sep 2015, Ian Campbell wrote:
> On Thu, 2015-09-24 at 23:19 +0100, Stefano Stabellini wrote:
> > On Thu, 24 Sep 2015, Ian Campbell wrote:
> > > On Thu, 2015-09-24 at 20:33 +0100, Stefano Stabellini wrote:
> > > > On Thu, 24 Sep 2015, Ian Campbell wrote:
> > > > > On Wed, 2015-09-23 at 18:36 +0100, Stefano Stabellini wrote:
> > > > > > On Wed, 23 Sep 2015, Ian Campbell wrote:
> > > > > > > On Tue, 2015-09-22 at 22:31 +0100, Stefano Stabellini wrote: 
> > > > > > > > The oldest Xen version I build-test for every pull request is
> > > > Xen 4.0.0,
> > > > > 
> > > > > I setup a build trees for 4.0 thru 4.6 yesterday to test this, what
> > > > a
> > > > > pain 4.1 and 4.0 are to build with a modern gcc! (Mostly newer
> > > > compiler
> > > > > warnings and mostly, but not all, fixes which I could just backport
> > > > > from newer Xen, the exceptions were a couple of things which were
> > > > > removed before they needed to be fixed)
> > > > > 
> > > > > > > > I think it is very reasonable to remove anything older than
> > > > that.
> > > > > > > > I am OK with removing Xen 4.0.0 too, but I would like a
> > > > warning to be
> > > > > > > > sent ahead of time to qemu-devel to see if anybody complains.
> > > > > > > 
> > > > > > > There is not much point in removing <=3.4 support and keeping
> > > > 4.0, since
> > > > > > > 4.0.0 was the last one which used a plain int as a handle,
> > > > anything older
> > > > > > > than 4.0.0 is trivial if 4.0.0 is supported.
> > > > > > > 
> > > > > > > One approach I am considering in order to keep 4.0.0 support
> > > > and earlier
> > > > > > > was to turn the "int fd" for <=4.0 into a pointer by having the
> > > > open
> > > > > > > wrapper do malloc(sizeof int) and the using wrappers do
> > > > xc_foo(*handle).
> > > > > > > 
> > > > > > > This way all the different variants take pointers and we have
> > > > less hoops to
> > > > > > > jump through to typedef everything in the correct way for each
> > > > variant.
> > > > > > > 
> > > > > > > If you would rather avoid doing that then I think dropping
> > > > 4.0.0 support
> > > > > > > would be the way to go and I'll send a mail to qemu-devel.
> > > > > >  
> > > > > > I would rather drop 4.0 support.
> > > > > 
> > > > > Supporting 4.0 didn't turn out quite as ugly as I had feared.
> > > > > 
> > > > > So before I send an email to qemu-devel to propose dropping 4.0
> > > > what do
> > > > > you think of the following which handles the evtchn case, there is
> > > > a
> > > > > similar patch for gnttab and a (yet to be written) patch for the
> > > > > foreign memory mapping case.
> > > > > 
> > > > > The relevant bit for this discussion is the 4.0.0 definition of
> > > > > xenevtchn_open in xen_common.h, the rest is just adjusting it to
> > > > use
> > > > > the API of the new library (for reasons explained in the commit
> > > > > message).
> > > > 
> > > > I think that it is OK in principle.
> > > > 
> > > > 
> > > > > diff --git a/include/hw/xen/xen_common.h
> > > > b/include/hw/xen/xen_common.h
> > > > > index 5923290..5700c1b 100644
> > > > > --- a/include/hw/xen/xen_common.h
> > > > > +++ b/include/hw/xen/xen_common.h
> > > > > @@ -39,17 +39,37 @@ static inline void *xc_map_foreign_bulk(int
> > > > xc_handle, uint32_t dom, int prot,
> > > > >  #if CONFIG_XEN_CTRL_INTERFACE_VERSION < 410
> > > > >  
> > > > >  typedef int XenXC;
> > > > > -typedef int XenEvtchn;
> > > > > +typedef int xenevtchn_handle;
> > > > >  typedef int XenGnttab;
> > > >  
> > > > ...
> > > > 
> > > > > @@ -108,17 +128,20 @@ static inline void xs_close(struct xs_handle
> > > > *xsh)
> > > > >  #else
> > > > >  
> > > > >  typedef xc_interface *XenXC;
> > > > > -typedef xc_evtchn *XenEvtchn;
> > > > > +typedef xc_evtchn xenevtchn_handle;
> > > > >  typedef xc_gnttab *XenGnttab;
> > > > >  
> > > > 
> > > > There is no reasons why we couldn't have a small compat shim on Xen >
> > > > 4.6 too, so I would change the definition of XenEvtchn for newer
> > > > versions of Xen and avoid some of the renaming in this patch to
> > > > reduce
> > > > the changes.
> > > > 
> > > > For example, why not define xc_evtchn_fd as xenevtchn_fd for Xen >
> > > > 4.6?
> > > > So that we don't need to go and rename all the call sites?
> > > 
> > > The idea was that the code would use the new stable API names from the
> > > stable libraries going forward, rather than using a shim to turn the
> > > stable APIs back into the old ones.
> > 
> > I don't think that is very important from QEMU's point of view, using a
> > shim is just fine, especially if it reduces the patch size to 5 lines of
> > code :-)
> 
> Is patch size really the major consideration here? IMHO it is simply less
> confusing to have no shim (since one doesn't need to translate the names
> when reading differing code bases) and with time the shim layers can drop
> away leading to less complexity.
>
> Also, I've already written all the patches, the renamings were very
> mechanical and at this point it would actually take me longer to undo them.
> 
> I'll do that if you insist, but I think the justification for sticking with
> a shim is very flimsy.

I just don't think is important to use the new names in QEMU. Of course
it is important to be consistent within the QEMU code base, but I don't
think is necessary or required to be consistent with external code
bases.  The shim has worked very well in QEMU for years and I am quite
happy to keep using it.

That said, there is nothing that screams "bished!" more than discussing
the naming scheme of xc calls in QEMU, so I won't draw the line on this.

^ permalink raw reply	[flat|nested] 55+ messages in thread

end of thread, other threads:[~2015-09-25 20:31 UTC | newest]

Thread overview: 55+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-07-15 15:46 [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries Ian Campbell
2015-07-15 15:46 ` [PATCH XEN v2 01/15] docs: Partial toolstack library API/ABI stabilisation Ian Campbell
2015-07-15 15:46 ` [PATCH XEN v2 02/15] tools/Rules.mk: Properly handle libraries with recursive dependcies Ian Campbell
2015-07-15 15:46 ` [PATCH XEN v2 03/15] tools: Refactor "xentoollog" into its own library Ian Campbell
2015-07-15 15:46 ` [PATCH XEN v2 04/15] tools/libxc: Remove osdep indirection for xc_evtchn Ian Campbell
2015-07-15 15:46 ` [PATCH XEN v2 05/15] tools: Refactor /dev/xen/evtchn wrappers into libxenevtchn Ian Campbell
2015-09-21 15:53   ` Ian Campbell
2015-07-15 15:46 ` [PATCH XEN v2 06/15] tools: Arrange to check public headers for ANSI compatiblity Ian Campbell
2015-07-15 15:46 ` [PATCH XEN v2 07/15] tools/libxc: Remove osdep indirection for xc_gnt{shr, tab} Ian Campbell
2015-07-15 15:46 ` [PATCH XEN v2 08/15] tools: Refactor /dev/xen/gnt{dev, shr} wrappers into libxengnttab Ian Campbell
2015-09-22 11:25   ` Ian Campbell
2015-09-22 11:36     ` Andrew Cooper
2015-09-22 12:41       ` Ian Jackson
2015-09-22 12:51         ` Ian Campbell
2015-07-15 15:46 ` [PATCH XEN v2 09/15] tools/libxc: Remove osdep indirection for privcmd Ian Campbell
     [not found]   ` <01C96D24-A13F-46A6-A8A9-5C04E2E199AF@citrix.com>
2015-07-16  7:59     ` Dave Scott
2015-07-16  8:35       ` Ian Campbell
2015-07-15 15:46 ` [PATCH XEN v2 10/15] tools: Refactor hypercall calling wrappers into libxencall Ian Campbell
2015-07-15 15:46 ` [PATCH XEN v2 11/15] tools/libxc: drop xc_map_foreign_bulk_compat wrappers Ian Campbell
2015-07-15 15:47 ` [PATCH XEN v2 12/15] tools: Remove xc_map_foreign_batch Ian Campbell
2015-07-15 16:08   ` George Dunlap
2015-07-15 15:47 ` [PATCH XEN v2 13/15] tools: Implement xc_map_foreign_range(s) in terms of common helper Ian Campbell
2015-07-15 15:47 ` [PATCH XEN v2 14/15] tools: Refactor foreign memory mapping into libxenforeignmemory Ian Campbell
2015-07-15 15:47 ` [PATCH XEN v2 15/15] HACK: Add a .config to pull all the right bits Ian Campbell
2015-07-15 15:47 ` [PATCH QEMUT v2 1/5] qemu-xen-traditional: Use xentoollog as a separate library Ian Campbell
2015-07-15 15:47 ` [PATCH QEMUT v2 2/5] qemu-xen-traditional: Use libxenevtchn Ian Campbell
2015-07-15 15:47 ` [PATCH QEMUT v2 3/5] qemu-xen-traditional: Use libxengnttab Ian Campbell
2015-07-15 15:47 ` [PATCH QEMUT v2 4/5] qemu-xen-traditional: Add libxencall to rpath-link Ian Campbell
2015-07-15 15:47 ` [PATCH QEMUT v2 5/5] qemu-xen-traditional: Add libxenforeignmemory " Ian Campbell
2015-07-15 15:48 ` [PATCH MINI-OS v2 1/5] mini-os: Include libxentoollog with libxc Ian Campbell
2015-07-15 15:48 ` [PATCH MINI-OS v2 2/5] mini-os: Include libxenevtchn " Ian Campbell
2015-07-15 15:48 ` [PATCH MINI-OS v2 3/5] mini-os: Include libxengnttab " Ian Campbell
2015-07-15 15:48 ` [PATCH MINI-OS v2 4/5] mini-os: Include libxencall " Ian Campbell
2015-07-15 15:48 ` [PATCH MINI-OS v2 5/5] mini-os: Include libxenforeignmemory " Ian Campbell
2015-07-15 15:53 ` [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries Andrew Cooper
2015-07-22 11:12   ` Ian Campbell
2015-07-22 12:58     ` Andrew Cooper
2015-07-22 13:05       ` Ian Campbell
2015-07-27  8:57     ` Ian Campbell
2015-09-22 15:03 ` Oldest supported Xen version in upstream QEMU (Was: Re: [Minios-devel] [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries) Ian Campbell
2015-09-22 21:31   ` Stefano Stabellini
2015-09-23  8:29     ` Ian Campbell
2015-09-23 14:09       ` Konrad Rzeszutek Wilk
2015-09-23 14:17         ` Juergen Gross
2015-09-23 14:21           ` Konrad Rzeszutek Wilk
2015-09-23 14:26             ` Ian Campbell
2015-09-23 17:36       ` Stefano Stabellini
2015-09-24  7:15         ` Ian Campbell
2015-09-24  9:03           ` Fabio Fantoni
2015-09-24 19:33           ` Stefano Stabellini
2015-09-24 21:11             ` Ian Campbell
2015-09-24 22:19               ` Stefano Stabellini
2015-09-25  8:27                 ` Ian Campbell
2015-09-25 20:31                   ` Stefano Stabellini
2015-09-24 16:47 ` [Minios-devel] [PATCH v2 0/15+5+5] Begin to disentangle libxenctrl and provide some stable libraries Ian Campbell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).