|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [xen master] tools/libxc: move libxenguest to tools/libs/guest
commit e3dd624e487c1aca1835138d3990f78af9906238
Author: Juergen Gross <jgross@xxxxxxxx>
AuthorDate: Fri Aug 28 17:07:35 2020 +0200
Commit: Wei Liu <wl@xxxxxxx>
CommitDate: Wed Sep 9 10:57:25 2020 +0000
tools/libxc: move libxenguest to tools/libs/guest
tools/libxc now contains libxenguest only. Move it to tools/libs/guest.
When generating the pkg-config file for libxenguest a filter is now
required for replacing "xenctrl" by "xencontrol" in the
"Requires.private:" entry. Add this filter to tools/libs/libs.mk.
Signed-off-by: Juergen Gross <jgross@xxxxxxxx>
Reviewed-by: Samuel Thibault <samuel.thibault@xxxxxxxxxxxx> (stubdom parts)
---
.gitignore | 16 +-
stubdom/Makefile | 34 +-
stubdom/grub/Makefile | 2 +-
stubdom/mini-os.mk | 2 +-
tools/Makefile | 3 +-
tools/Rules.mk | 7 +-
tools/libs/Makefile | 1 +
tools/libs/guest/COPYING | 467 +++++
tools/libs/guest/Makefile | 121 ++
tools/libs/guest/include/xenguest.h | 327 ++++
tools/libs/guest/xg_cpuid_x86.c | 665 +++++++
tools/libs/guest/xg_dom_arm.c | 552 ++++++
tools/libs/guest/xg_dom_armzimageloader.c | 271 +++
tools/libs/guest/xg_dom_binloader.c | 329 ++++
tools/libs/guest/xg_dom_boot.c | 451 +++++
tools/libs/guest/xg_dom_bzimageloader.c | 812 +++++++++
tools/libs/guest/xg_dom_compat_linux.c | 97 +
tools/libs/guest/xg_dom_core.c | 1272 ++++++++++++++
tools/libs/guest/xg_dom_decompress.h | 8 +
tools/libs/guest/xg_dom_decompress_lz4.c | 141 ++
tools/libs/guest/xg_dom_decompress_unsafe.c | 48 +
tools/libs/guest/xg_dom_decompress_unsafe.h | 20 +
tools/libs/guest/xg_dom_decompress_unsafe_bzip2.c | 14 +
tools/libs/guest/xg_dom_decompress_unsafe_lzma.c | 14 +
tools/libs/guest/xg_dom_decompress_unsafe_lzo1x.c | 50 +
tools/libs/guest/xg_dom_decompress_unsafe_xz.c | 46 +
tools/libs/guest/xg_dom_elfloader.c | 249 +++
tools/libs/guest/xg_dom_hvmloader.c | 264 +++
tools/libs/guest/xg_dom_x86.c | 1945 +++++++++++++++++++++
tools/libs/guest/xg_domain.c | 149 ++
tools/libs/guest/xg_nomigrate.c | 50 +
tools/libs/guest/xg_offline_page.c | 708 ++++++++
tools/libs/guest/xg_private.c | 198 +++
tools/libs/guest/xg_private.h | 124 ++
tools/libs/guest/xg_save_restore.h | 134 ++
tools/libs/guest/xg_sr_common.c | 167 ++
tools/libs/guest/xg_sr_common.h | 468 +++++
tools/libs/guest/xg_sr_common_x86.c | 173 ++
tools/libs/guest/xg_sr_common_x86.h | 51 +
tools/libs/guest/xg_sr_common_x86_pv.c | 193 ++
tools/libs/guest/xg_sr_common_x86_pv.h | 109 ++
tools/libs/guest/xg_sr_restore.c | 986 +++++++++++
tools/libs/guest/xg_sr_restore_x86_hvm.c | 274 +++
tools/libs/guest/xg_sr_restore_x86_pv.c | 1210 +++++++++++++
tools/libs/guest/xg_sr_save.c | 1059 +++++++++++
tools/libs/guest/xg_sr_save_x86_hvm.c | 251 +++
tools/libs/guest/xg_sr_save_x86_pv.c | 1156 ++++++++++++
tools/libs/guest/xg_sr_stream_format.h | 150 ++
tools/libs/guest/xg_suspend.c | 202 +++
tools/libs/libs.mk | 2 +-
tools/libs/uselibs.mk | 2 +
tools/libxc/COPYING | 467 -----
tools/libxc/Makefile | 219 ---
tools/libxc/include/xenguest.h | 327 ----
tools/libxc/xg_cpuid_x86.c | 665 -------
tools/libxc/xg_dom_arm.c | 552 ------
tools/libxc/xg_dom_armzimageloader.c | 271 ---
tools/libxc/xg_dom_binloader.c | 329 ----
tools/libxc/xg_dom_boot.c | 451 -----
tools/libxc/xg_dom_bzimageloader.c | 812 ---------
tools/libxc/xg_dom_compat_linux.c | 97 -
tools/libxc/xg_dom_core.c | 1272 --------------
tools/libxc/xg_dom_decompress.h | 8 -
tools/libxc/xg_dom_decompress_lz4.c | 141 --
tools/libxc/xg_dom_decompress_unsafe.c | 48 -
tools/libxc/xg_dom_decompress_unsafe.h | 20 -
tools/libxc/xg_dom_decompress_unsafe_bzip2.c | 14 -
tools/libxc/xg_dom_decompress_unsafe_lzma.c | 14 -
tools/libxc/xg_dom_decompress_unsafe_lzo1x.c | 50 -
tools/libxc/xg_dom_decompress_unsafe_xz.c | 46 -
tools/libxc/xg_dom_elfloader.c | 249 ---
tools/libxc/xg_dom_hvmloader.c | 264 ---
tools/libxc/xg_dom_x86.c | 1945 ---------------------
tools/libxc/xg_domain.c | 149 --
tools/libxc/xg_nomigrate.c | 50 -
tools/libxc/xg_offline_page.c | 708 --------
tools/libxc/xg_private.c | 198 ---
tools/libxc/xg_private.h | 124 --
tools/libxc/xg_save_restore.h | 134 --
tools/libxc/xg_sr_common.c | 167 --
tools/libxc/xg_sr_common.h | 468 -----
tools/libxc/xg_sr_common_x86.c | 173 --
tools/libxc/xg_sr_common_x86.h | 51 -
tools/libxc/xg_sr_common_x86_pv.c | 193 --
tools/libxc/xg_sr_common_x86_pv.h | 109 --
tools/libxc/xg_sr_restore.c | 986 -----------
tools/libxc/xg_sr_restore_x86_hvm.c | 274 ---
tools/libxc/xg_sr_restore_x86_pv.c | 1210 -------------
tools/libxc/xg_sr_save.c | 1059 -----------
tools/libxc/xg_sr_save_x86_hvm.c | 251 ---
tools/libxc/xg_sr_save_x86_pv.c | 1156 ------------
tools/libxc/xg_sr_stream_format.h | 150 --
tools/libxc/xg_suspend.c | 202 ---
93 files changed, 16002 insertions(+), 16115 deletions(-)
diff --git a/.gitignore b/.gitignore
index d22b031ed2..eb637a98e9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -71,7 +71,6 @@ stubdom/include
stubdom/ioemu
stubdom/ioemu/
stubdom/libs-*
-stubdom/libxc-*
stubdom/libxencall-*
stubdom/libxenevtchn-*
stubdom/libxenforeignmemory-*
@@ -121,6 +120,14 @@ tools/libs/foreignmemory/headers.chk
tools/libs/foreignmemory/xenforeignmemory.pc
tools/libs/devicemodel/headers.chk
tools/libs/devicemodel/xendevicemodel.pc
+tools/libs/guest/_*.[ch]
+tools/libs/guest/libxenguest.map
+tools/libs/guest/xenguest.pc
+tools/libs/guest/xc_bitops.h
+tools/libs/guest/xc_core.h
+tools/libs/guest/xc_core_arm.h
+tools/libs/guest/xc_core_x86.h
+tools/libs/guest/xc_private.h
tools/console/xenconsole
tools/console/xenconsoled
tools/console/client/_paths.h
@@ -197,12 +204,6 @@ tools/include/xen-xsm/*
tools/include/xen-foreign/*.(c|h|size)
tools/include/xen-foreign/checker
tools/libvchan/xenvchan.pc
-tools/libxc/*.pc
-tools/libxc/xc_bitops.h
-tools/libxc/xc_core.h
-tools/libxc/xc_core_arm.h
-tools/libxc/xc_core_x86.h
-tools/libxc/xc_private.h
tools/libxl/_libxl.api-for-check
tools/libxl/*.api-ok
tools/libxl/*.pc
@@ -370,7 +371,6 @@ tools/include/xen-foreign/arm64.h
tools/misc/xen-hptool
tools/misc/xen-mfndump
tools/libs/toolcore/include/_*.h
-tools/libxc/_*.[ch]
tools/libxl/_*.[ch]
tools/libxl/testidl
tools/libxl/testidl.c
diff --git a/stubdom/Makefile b/stubdom/Makefile
index 6c481285ec..fb9617fa14 100644
--- a/stubdom/Makefile
+++ b/stubdom/Makefile
@@ -331,7 +331,9 @@ endif
# libraries under tools/libs
#######
-STUB_LIBS := toolcore toollog evtchn gnttab call foreignmemory devicemodel ctrl
+STUB_LIBS := toolcore toollog evtchn gnttab call foreignmemory devicemodel
ctrl guest
+
+LIBDEP_guest := cross-zlib
#######
# common handling
@@ -362,13 +364,10 @@ endef
$(foreach lib,$(STUB_LIBS),$(eval $(call BUILD_lib,$(lib))))
-libxc-$(XEN_TARGET_ARCH)/stamp: $(XEN_ROOT)/tools/libxc/Makefile
- $(do_links)
-
xenstore/stamp: $(XEN_ROOT)/tools/xenstore/Makefile
$(do_links)
-LINK_DIRS := libxc-$(XEN_TARGET_ARCH) xenstore $(foreach
dir,$(STUB_LIBS),libs-$(XEN_TARGET_ARCH)/$(dir))
+LINK_DIRS := xenstore $(foreach
dir,$(STUB_LIBS),libs-$(XEN_TARGET_ARCH)/$(dir))
LINK_STAMPS := $(foreach dir,$(LINK_DIRS),$(dir)/stamp)
mk-headers-$(XEN_TARGET_ARCH): $(IOEMU_LINKFARM_TARGET) $(LINK_STAMPS)
@@ -391,16 +390,6 @@ $(TARGETS_MINIOS): mini-os-%:
mkdir -p $@/$$i ; \
done
-#######
-# libxc
-#######
-
-.PHONY: libxc
-libxc: libxc-$(XEN_TARGET_ARCH)/libxenguest.a
-libxc-$(XEN_TARGET_ARCH)/libxenguest.a: libxenevtchn libxenctrl cross-zlib
-libxc-$(XEN_TARGET_ARCH)/libxenguest.a: mk-headers-$(XEN_TARGET_ARCH)
$(NEWLIB_STAMPFILE)
- CPPFLAGS="$(TARGET_CPPFLAGS)" CFLAGS="$(TARGET_CFLAGS)" $(MAKE)
DESTDIR= CONFIG_LIBXC_MINIOS=y -C libxc-$(XEN_TARGET_ARCH)
-
#######
# ioemu
#######
@@ -409,7 +398,7 @@ ioemu-minios-config.mk: $(CURDIR)/ioemu-minios.cfg
MINIOS_CONFIG="$<" CONFIG_FILE="$(CURDIR)/$@" $(MAKE) DESTDIR= -C
$(MINI_OS) config
.PHONY: ioemu
-ioemu: cross-zlib cross-libpci libxc ioemu-minios-config.mk
+ioemu: cross-zlib cross-libpci libxenguest ioemu-minios-config.mk
[ -f ioemu/config-host.mak ] || \
( $(buildmakevars2shellvars); \
cd ioemu ; \
@@ -503,15 +492,15 @@ xenstore: $(CROSS_ROOT) xenstore-minios-config.mk
.PHONY: ioemu-stubdom
ioemu-stubdom: APP_OBJS=$(CURDIR)/ioemu/i386-stubdom/qemu.a
$(CURDIR)/ioemu/i386-stubdom/libqemu.a $(CURDIR)/ioemu/libqemu_common.a
-ioemu-stubdom: mini-os-$(XEN_TARGET_ARCH)-ioemu lwip-$(XEN_TARGET_ARCH) libxc
ioemu
+ioemu-stubdom: mini-os-$(XEN_TARGET_ARCH)-ioemu lwip-$(XEN_TARGET_ARCH)
libxenguest ioemu
DEF_CPPFLAGS="$(TARGET_CPPFLAGS)" DEF_CFLAGS="$(TARGET_CFLAGS)"
DEF_LDFLAGS="$(TARGET_LDFLAGS)" MINIOS_CONFIG="$(CURDIR)/ioemu-minios.cfg"
$(MAKE) DESTDIR= -C $(MINI_OS) OBJ_DIR=$(CURDIR)/$<
LWIPDIR=$(CURDIR)/lwip-$(XEN_TARGET_ARCH) APP_OBJS="$(APP_OBJS)"
.PHONY: caml-stubdom
-caml-stubdom: mini-os-$(XEN_TARGET_ARCH)-caml lwip-$(XEN_TARGET_ARCH) libxc
cross-ocaml caml
+caml-stubdom: mini-os-$(XEN_TARGET_ARCH)-caml lwip-$(XEN_TARGET_ARCH)
libxenguest cross-ocaml caml
DEF_CPPFLAGS="$(TARGET_CPPFLAGS)" DEF_CFLAGS="$(TARGET_CFLAGS)"
DEF_LDFLAGS="$(TARGET_LDFLAGS)" MINIOS_CONFIG="$(CURDIR)/caml/minios.cfg"
$(MAKE) DESTDIR= -C $(MINI_OS) OBJ_DIR=$(CURDIR)/$<
LWIPDIR=$(CURDIR)/lwip-$(XEN_TARGET_ARCH) APP_OBJS="$(CURDIR)/caml/main-caml.o
$(CURDIR)/caml/caml.o $(CAMLLIB)/libasmrun.a"
.PHONY: c-stubdom
-c-stubdom: mini-os-$(XEN_TARGET_ARCH)-c lwip-$(XEN_TARGET_ARCH) libxc c
+c-stubdom: mini-os-$(XEN_TARGET_ARCH)-c lwip-$(XEN_TARGET_ARCH) libxenguest c
DEF_CPPFLAGS="$(TARGET_CPPFLAGS)" DEF_CFLAGS="$(TARGET_CFLAGS)"
DEF_LDFLAGS="$(TARGET_LDFLAGS)" MINIOS_CONFIG="$(CURDIR)/c/minios.cfg" $(MAKE)
DESTDIR= -C $(MINI_OS) OBJ_DIR=$(CURDIR)/$<
LWIPDIR=$(CURDIR)/lwip-$(XEN_TARGET_ARCH) APP_OBJS=$(CURDIR)/c/main.a
.PHONY: vtpm-stubdom
@@ -523,11 +512,11 @@ vtpmmgr-stubdom: mini-os-$(XEN_TARGET_ARCH)-vtpmmgr
vtpmmgr
DEF_CPPFLAGS="$(TARGET_CPPFLAGS)" DEF_CFLAGS="$(TARGET_CFLAGS)"
DEF_LDFLAGS="$(TARGET_LDFLAGS)" MINIOS_CONFIG="$(CURDIR)/vtpmmgr/minios.cfg"
$(MAKE) -C $(MINI_OS) OBJ_DIR=$(CURDIR)/$<
APP_OBJS="$(CURDIR)/vtpmmgr/vtpmmgr.a" APP_LDLIBS="-lm -lpolarssl"
.PHONY: pv-grub
-pv-grub: mini-os-$(XEN_TARGET_ARCH)-grub libxc grub
+pv-grub: mini-os-$(XEN_TARGET_ARCH)-grub libxenguest grub
DEF_CPPFLAGS="$(TARGET_CPPFLAGS)" DEF_CFLAGS="$(TARGET_CFLAGS)"
DEF_LDFLAGS="$(TARGET_LDFLAGS)" MINIOS_CONFIG="$(CURDIR)/grub/minios.cfg"
$(MAKE) DESTDIR= -C $(MINI_OS) OBJ_DIR=$(CURDIR)/$<
APP_OBJS=$(CURDIR)/grub-$(XEN_TARGET_ARCH)/main.a
.PHONY: xenstore-stubdom
-xenstore-stubdom: mini-os-$(XEN_TARGET_ARCH)-xenstore libxc xenstore
+xenstore-stubdom: mini-os-$(XEN_TARGET_ARCH)-xenstore libxenguest xenstore
DEF_CPPFLAGS="$(TARGET_CPPFLAGS)" DEF_CFLAGS="$(TARGET_CFLAGS)"
DEF_LDFLAGS="$(TARGET_LDFLAGS)" MINIOS_CONFIG="$(CURDIR)/xenstore-minios.cfg"
$(MAKE) DESTDIR= -C $(MINI_OS) OBJ_DIR=$(CURDIR)/$<
APP_OBJS=$(CURDIR)/xenstore/xenstored.a
#########
@@ -621,7 +610,6 @@ clean:
rm -f $(STUBDOMPATH)
rm -f *-minios-config.mk
rm -fr pkg-config
- [ ! -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
@@ -632,7 +620,7 @@ crossclean: clean
rm -fr newlib-$(XEN_TARGET_ARCH)
rm -fr zlib-$(XEN_TARGET_ARCH) pciutils-$(XEN_TARGET_ARCH)
rm -fr libs-$(XEN_TARGET_ARCH)
- rm -fr libxc-$(XEN_TARGET_ARCH) ioemu xenstore
+ rm -fr ioemu xenstore
rm -fr gmp-$(XEN_TARGET_ARCH)
rm -fr polarssl-$(XEN_TARGET_ARCH)
rm -fr openssl-$(XEN_TARGET_ARCH)
diff --git a/stubdom/grub/Makefile b/stubdom/grub/Makefile
index d33fa2f71e..7397661c9b 100644
--- a/stubdom/grub/Makefile
+++ b/stubdom/grub/Makefile
@@ -7,7 +7,7 @@ BOOT=$(OBJ_DIR)/boot-$(XEN_TARGET_ARCH).o
DEF_CPPFLAGS += -I$(XEN_ROOT)/tools/libs/toollog/include
DEF_CPPFLAGS += -I$(XEN_ROOT)/tools/libs/ctrl/include
-DEF_CPPFLAGS += -I$(XEN_ROOT)/tools/libxc/include
+DEF_CPPFLAGS += -I$(XEN_ROOT)/tools/libs/guest/include
DEF_CPPFLAGS += -I$(XEN_ROOT)/tools/include -I.
DEF_CPPFLAGS += -I../grub-upstream/stage1
DEF_CPPFLAGS += -I../grub-upstream/stage2
diff --git a/stubdom/mini-os.mk b/stubdom/mini-os.mk
index b1387df3f8..e1640a7cbc 100644
--- a/stubdom/mini-os.mk
+++ b/stubdom/mini-os.mk
@@ -14,4 +14,4 @@ CALL_PATH =
$(XEN_ROOT)/stubdom/libs-$(MINIOS_TARGET_ARCH)/call
FOREIGNMEMORY_PATH =
$(XEN_ROOT)/stubdom/libs-$(MINIOS_TARGET_ARCH)/foreignmemory
DEVICEMODEL_PATH = $(XEN_ROOT)/stubdom/libs-$(MINIOS_TARGET_ARCH)/devicemodel
CTRL_PATH = $(XEN_ROOT)/stubdom/libs-$(MINIOS_TARGET_ARCH)/ctrl
-GUEST_PATH = $(XEN_ROOT)/stubdom/libxc-$(MINIOS_TARGET_ARCH)
+GUEST_PATH = $(XEN_ROOT)/stubdom/libs-$(MINIOS_TARGET_ARCH)/guest
diff --git a/tools/Makefile b/tools/Makefile
index 7c9f9fc900..f9b4012290 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -6,7 +6,6 @@ include $(XEN_ROOT)/tools/Rules.mk
SUBDIRS-y :=
SUBDIRS-y += libs
-SUBDIRS-y += libxc
SUBDIRS-y += flask
SUBDIRS-y += fuzz
SUBDIRS-y += xenstore
@@ -44,7 +43,7 @@ SUBDIRS-y += pygrub
SUBDIRS-$(OCAML_TOOLS) += ocaml
ifeq ($(CONFIG_RUMP),y)
-SUBDIRS-y := libs libxc xenstore
+SUBDIRS-y := libs xenstore
endif
# For the sake of linking, set the sys-root
diff --git a/tools/Rules.mk b/tools/Rules.mk
index 35940cb338..e17ac3ecc6 100644
--- a/tools/Rules.mk
+++ b/tools/Rules.mk
@@ -15,7 +15,6 @@ XEN_INCLUDE = $(XEN_ROOT)/tools/include
include $(XEN_ROOT)/tools/libs/uselibs.mk
-XEN_libxenguest = $(XEN_ROOT)/tools/libxc
XEN_libxenlight = $(XEN_ROOT)/tools/libxl
# Currently libxlutil lives in the same directory as libxenlight
XEN_libxlutil = $(XEN_libxenlight)
@@ -105,11 +104,7 @@ $(foreach lib,$(LIBS_LIBS),$(eval $(call LIB_defs,$(lib))))
# code which compiles against libxenctrl get __XEN_TOOLS__ and
# therefore sees the unstable hypercall interfaces.
CFLAGS_libxenctrl += $(CFLAGS_libxentoollog) $(CFLAGS_libxenforeignmemory)
$(CFLAGS_libxendevicemodel) -D__XEN_TOOLS__
-
-CFLAGS_libxenguest = -I$(XEN_libxenguest)/include $(CFLAGS_libxenevtchn)
$(CFLAGS_libxenforeignmemory) $(CFLAGS_xeninclude)
-SHDEPS_libxenguest = $(SHLIB_libxenevtchn) $(SHLIB_libxenctrl)
-LDLIBS_libxenguest = $(SHDEPS_libxenguest)
$(XEN_libxenguest)/libxenguest$(libextension)
-SHLIB_libxenguest = $(SHDEPS_libxenguest) -Wl,-rpath-link=$(XEN_libxenguest)
+CFLAGS_libxenguest += $(CFLAGS_libxenevtchn) $(CFLAGS_libxenforeignmemory)
CFLAGS_libxenstore = -I$(XEN_libxenstore)/include $(CFLAGS_xeninclude)
SHDEPS_libxenstore = $(SHLIB_libxentoolcore) $(SHLIB_libxenctrl)
diff --git a/tools/libs/Makefile b/tools/libs/Makefile
index 7648ea0e4c..f15c1688f7 100644
--- a/tools/libs/Makefile
+++ b/tools/libs/Makefile
@@ -10,6 +10,7 @@ SUBDIRS-y += call
SUBDIRS-y += foreignmemory
SUBDIRS-y += devicemodel
SUBDIRS-y += ctrl
+SUBDIRS-y += guest
SUBDIRS-y += hypfs
ifeq ($(CONFIG_RUMP),y)
diff --git a/tools/libs/guest/COPYING b/tools/libs/guest/COPYING
new file mode 100644
index 0000000000..7ca8702509
--- /dev/null
+++ b/tools/libs/guest/COPYING
@@ -0,0 +1,467 @@
+Note that the only valid version of the LGPL as far as the files in
+this directory (and its subdirectories) are concerned is _this_
+particular version of the license (i.e., *only* v2.1, not v2.2 or v3.x
+or whatever), unless explicitly otherwise stated.
+
+Where clause 3 is invoked in order to relicense under the GPL then
+this shall be considered to be GPL v2 only for files which have
+specified LGPL v2.1 only.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
diff --git a/tools/libs/guest/Makefile b/tools/libs/guest/Makefile
new file mode 100644
index 0000000000..e53aeabd3e
--- /dev/null
+++ b/tools/libs/guest/Makefile
@@ -0,0 +1,121 @@
+XEN_ROOT = $(CURDIR)/../../..
+include $(XEN_ROOT)/tools/Rules.mk
+
+ifeq ($(CONFIG_LIBXC_MINIOS),y)
+# Save/restore of a domain is currently incompatible with a stubdom environment
+override CONFIG_MIGRATE := n
+endif
+
+LINK_FILES := xc_private.h xc_core.h xc_core_x86.h xc_core_arm.h xc_bitops.h
+
+$(LINK_FILES):
+ ln -sf $(XEN_ROOT)/tools/libs/ctrl/$(notdir $@) $@
+
+SRCS-y += xg_private.c
+SRCS-y += xg_domain.c
+SRCS-y += xg_suspend.c
+ifeq ($(CONFIG_MIGRATE),y)
+SRCS-y += xg_sr_common.c
+SRCS-$(CONFIG_X86) += xg_sr_common_x86.c
+SRCS-$(CONFIG_X86) += xg_sr_common_x86_pv.c
+SRCS-$(CONFIG_X86) += xg_sr_restore_x86_pv.c
+SRCS-$(CONFIG_X86) += xg_sr_restore_x86_hvm.c
+SRCS-$(CONFIG_X86) += xg_sr_save_x86_pv.c
+SRCS-$(CONFIG_X86) += xg_sr_save_x86_hvm.c
+SRCS-y += xg_sr_restore.c
+SRCS-y += xg_sr_save.c
+SRCS-y += xg_offline_page.c
+else
+SRCS-y += xg_nomigrate.c
+endif
+
+vpath %.c ../../../xen/common/libelf
+CFLAGS += -I../../../xen/common/libelf
+
+ELF_SRCS-y += libelf-tools.c libelf-loader.c
+ELF_SRCS-y += libelf-dominfo.c
+
+SRCS-y += $(ELF_SRCS-y)
+
+$(patsubst %.c,%.o,$(ELF_SRCS-y)): CFLAGS += -Wno-pointer-sign
+$(patsubst %.c,%.opic,$(ELF_SRCS-y)): CFLAGS += -Wno-pointer-sign
+
+ifeq ($(CONFIG_X86),y) # Add libx86 to the build
+vpath %.c ../../../xen/lib/x86
+
+SRCS-y += cpuid.c msr.c
+endif
+
+# new domain builder
+SRCS-y += xg_dom_core.c
+SRCS-y += xg_dom_boot.c
+SRCS-y += xg_dom_elfloader.c
+SRCS-$(CONFIG_X86) += xg_dom_bzimageloader.c
+SRCS-$(CONFIG_X86) += xg_dom_decompress_lz4.c
+SRCS-$(CONFIG_X86) += xg_dom_hvmloader.c
+SRCS-$(CONFIG_ARM) += xg_dom_armzimageloader.c
+SRCS-y += xg_dom_binloader.c
+SRCS-y += xg_dom_compat_linux.c
+
+SRCS-$(CONFIG_X86) += xg_dom_x86.c
+SRCS-$(CONFIG_X86) += xg_cpuid_x86.c
+SRCS-$(CONFIG_ARM) += xg_dom_arm.c
+
+ifeq ($(CONFIG_LIBXC_MINIOS),y)
+SRCS-y += xg_dom_decompress_unsafe.c
+SRCS-y += xg_dom_decompress_unsafe_bzip2.c
+SRCS-y += xg_dom_decompress_unsafe_lzma.c
+SRCS-y += xg_dom_decompress_unsafe_lzo1x.c
+SRCS-y += xg_dom_decompress_unsafe_xz.c
+endif
+
+-include $(XEN_TARGET_ARCH)/Makefile
+
+CFLAGS += -Werror -Wmissing-prototypes
+CFLAGS += -I. -I./include $(CFLAGS_xeninclude)
+CFLAGS += -D__XEN_TOOLS__
+CFLAGS += -include $(XEN_ROOT)/tools/config.h
+
+# Needed for posix_fadvise64() in xc_linux.c
+CFLAGS-$(CONFIG_Linux) += -D_GNU_SOURCE
+
+CFLAGS += $(PTHREAD_CFLAGS)
+CFLAGS += $(CFLAGS_libxentoollog)
+CFLAGS += $(CFLAGS_libxenevtchn)
+CFLAGS += $(CFLAGS_libxendevicemodel)
+
+# libxenguest includes xc_private.h, so needs this despite not using
+# this functionality directly.
+CFLAGS += $(CFLAGS_libxencall) $(CFLAGS_libxenforeignmemory)
+
+ifeq ($(CONFIG_MiniOS),y)
+zlib-options =
+else
+zlib-options = $(ZLIB)
+endif
+
+xc_dom_bzimageloader.o: CFLAGS += $(filter -D%,$(zlib-options))
+xc_dom_bzimageloader.opic: CFLAGS += $(filter -D%,$(zlib-options))
+
+LIBHEADER := xenguest.h
+
+NO_HEADERS_CHK := y
+
+include $(XEN_ROOT)/tools/libs/libs.mk
+
+libxenguest.so.$(MAJOR).$(MINOR): COMPRESSION_LIBS = $(filter
-l%,$(zlib-options))
+libxenguest.so.$(MAJOR).$(MINOR): APPEND_LDFLAGS += $(COMPRESSION_LIBS) -lz
+
+genpath-target = $(call buildmakevars2header,_paths.h)
+$(eval $(genpath-target))
+
+xc_private.h: _paths.h
+
+$(LIB_OBJS) $(PIC_OBJS): $(LINK_FILES)
+
+$(PKG_CONFIG_LOCAL): PKG_CONFIG_INCDIR = $(XEN_libxenctrl)/include
+$(PKG_CONFIG_LOCAL): PKG_CONFIG_CFLAGS_LOCAL = $(CFLAGS_xeninclude)
+
+.PHONY: cleanlocal
+cleanlocal:
+ rm -f libxenguest.map
diff --git a/tools/libs/guest/include/xenguest.h
b/tools/libs/guest/include/xenguest.h
new file mode 100644
index 0000000000..4643384790
--- /dev/null
+++ b/tools/libs/guest/include/xenguest.h
@@ -0,0 +1,327 @@
+/******************************************************************************
+ * xenguest.h
+ *
+ * A library for guest domain management in Xen.
+ *
+ * Copyright (c) 2003-2004, K A Fraser.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef XENGUEST_H
+#define XENGUEST_H
+
+#include <xenctrl_dom.h>
+
+#define XC_NUMA_NO_NODE (~0U)
+
+#define XCFLAGS_LIVE (1 << 0)
+#define XCFLAGS_DEBUG (1 << 1)
+
+#define X86_64_B_SIZE 64
+#define X86_32_B_SIZE 32
+
+/*
+ * User not using xc_suspend_* / xc_await_suspent may not want to
+ * include the full libxenevtchn API here.
+ */
+struct xenevtchn_handle;
+
+/* For save's precopy_policy(). */
+struct precopy_stats
+{
+ unsigned int iteration;
+ unsigned int total_written;
+ long dirty_count; /* -1 if unknown */
+};
+
+/*
+ * A precopy_policy callback may not be running in the same address
+ * space as libxc an so precopy_stats is passed by value.
+ */
+typedef int (*precopy_policy_t)(struct precopy_stats, void *);
+
+/* callbacks provided by xc_domain_save */
+struct save_callbacks {
+ /*
+ * Called after expiration of checkpoint interval,
+ * to suspend the guest.
+ */
+ int (*suspend)(void *data);
+
+ /*
+ * Called before and after every batch of page data sent during
+ * the precopy phase of a live migration to ask the caller what
+ * to do next based on the current state of the precopy migration.
+ *
+ * Should return one of the values listed below:
+ */
+#define XGS_POLICY_ABORT (-1) /* Abandon the migration entirely
+ * and tidy up. */
+#define XGS_POLICY_CONTINUE_PRECOPY 0 /* Remain in the precopy phase. */
+#define XGS_POLICY_STOP_AND_COPY 1 /* Immediately suspend and transmit the
+ * remaining dirty pages. */
+ precopy_policy_t precopy_policy;
+
+ /*
+ * Called after the guest's dirty pages have been
+ * copied into an output buffer.
+ * Callback function resumes the guest & the device model,
+ * returns to xc_domain_save.
+ * xc_domain_save then flushes the output buffer, while the
+ * guest continues to run.
+ */
+ int (*postcopy)(void *data);
+
+ /*
+ * Called after the memory checkpoint has been flushed
+ * out into the network. Typical actions performed in this
+ * callback include:
+ * (a) send the saved device model state (for HVM guests),
+ * (b) wait for checkpoint ack
+ * (c) release the network output buffer pertaining to the acked
checkpoint.
+ * (c) sleep for the checkpoint interval.
+ *
+ * returns:
+ * 0: terminate checkpointing gracefully
+ * 1: take another checkpoint
+ */
+ int (*checkpoint)(void *data);
+
+ /*
+ * Called after the checkpoint callback.
+ *
+ * returns:
+ * 0: terminate checkpointing gracefully
+ * 1: take another checkpoint
+ */
+ int (*wait_checkpoint)(void *data);
+
+ /* Enable qemu-dm logging dirty pages to xen */
+ int (*switch_qemu_logdirty)(uint32_t domid, unsigned enable, void *data);
/* HVM only */
+
+ /* to be provided as the last argument to each callback function */
+ void *data;
+};
+
+/* Type of stream. Plain, or using a continuous replication protocol? */
+typedef enum {
+ XC_STREAM_PLAIN,
+ XC_STREAM_REMUS,
+ XC_STREAM_COLO,
+} xc_stream_type_t;
+
+/**
+ * This function will save a running domain.
+ *
+ * @param xch a handle to an open hypervisor interface
+ * @param io_fd the file descriptor to save a domain to
+ * @param dom the id of the domain
+ * @param flags XCFLAGS_xxx
+ * @param stream_type XC_STREAM_PLAIN if the far end of the stream
+ * doesn't use checkpointing
+ * @param recv_fd Only used for XC_STREAM_COLO. Contains backchannel from
+ * the destination side.
+ * @return 0 on success, -1 on failure
+ */
+int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom,
+ uint32_t flags, struct save_callbacks *callbacks,
+ xc_stream_type_t stream_type, int recv_fd);
+
+/* callbacks provided by xc_domain_restore */
+struct restore_callbacks {
+ /*
+ * Called once the STATIC_DATA_END record has been received/inferred.
+ *
+ * For compatibility with older streams, provides a list of static data
+ * expected to be found in the stream, which was missing. A higher level
+ * toolstack is responsible for providing any necessary compatibiltiy.
+ */
+#define XGR_SDD_MISSING_CPUID (1 << 0)
+#define XGR_SDD_MISSING_MSR (1 << 1)
+ int (*static_data_done)(unsigned int missing, void *data);
+
+ /* Called after a new checkpoint to suspend the guest. */
+ int (*suspend)(void *data);
+
+ /*
+ * Called after the secondary vm is ready to resume.
+ * Callback function resumes the guest & the device model,
+ * returns to xc_domain_restore.
+ */
+ int (*postcopy)(void *data);
+
+ /*
+ * A checkpoint record has been found in the stream.
+ * returns:
+ */
+#define XGR_CHECKPOINT_ERROR 0 /* Terminate processing */
+#define XGR_CHECKPOINT_SUCCESS 1 /* Continue reading more data from the
stream */
+#define XGR_CHECKPOINT_FAILOVER 2 /* Failover and resume VM */
+ int (*checkpoint)(void *data);
+
+ /*
+ * Called after the checkpoint callback.
+ *
+ * returns:
+ * 0: terminate checkpointing gracefully
+ * 1: take another checkpoint
+ */
+ int (*wait_checkpoint)(void *data);
+
+ /*
+ * callback to send store gfn and console gfn to xl
+ * if we want to resume vm before xc_domain_save()
+ * exits.
+ */
+ void (*restore_results)(xen_pfn_t store_gfn, xen_pfn_t console_gfn,
+ void *data);
+
+ /* to be provided as the last argument to each callback function */
+ void *data;
+};
+
+/**
+ * This function will restore a saved domain.
+ *
+ * Domain is restored in a suspended state ready to be unpaused.
+ *
+ * @param xch a handle to an open hypervisor interface
+ * @param io_fd the file descriptor to restore a domain from
+ * @param dom the id of the domain
+ * @param store_evtchn the xenstore event channel for this domain to use
+ * @param store_mfn filled with the gfn of the store page
+ * @param store_domid the backend domain for xenstore
+ * @param console_evtchn the console event channel for this domain to use
+ * @param console_mfn filled with the gfn of the console page
+ * @param console_domid the backend domain for xenconsole
+ * @param stream_type XC_STREAM_PLAIN if the far end of the stream is using
+ * checkpointing
+ * @param callbacks non-NULL to receive a callback to restore toolstack
+ * specific data
+ * @param send_back_fd Only used for XC_STREAM_COLO. Contains backchannel to
+ * the source side.
+ * @return 0 on success, -1 on failure
+ */
+int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
+ unsigned int store_evtchn, unsigned long *store_mfn,
+ uint32_t store_domid, unsigned int console_evtchn,
+ unsigned long *console_mfn, uint32_t console_domid,
+ xc_stream_type_t stream_type,
+ struct restore_callbacks *callbacks, int send_back_fd);
+
+/**
+ * This function will create a domain for a paravirtualized Linux
+ * using file names pointing to kernel and ramdisk
+ *
+ * @parm xch a handle to an open hypervisor interface
+ * @parm domid the id of the domain
+ * @parm mem_mb memory size in megabytes
+ * @parm image_name name of the kernel image file
+ * @parm ramdisk_name name of the ramdisk image file
+ * @parm cmdline command line string
+ * @parm flags domain creation flags
+ * @parm store_evtchn the store event channel for this domain to use
+ * @parm store_mfn returned with the mfn of the store page
+ * @parm console_evtchn the console event channel for this domain to use
+ * @parm conole_mfn returned with the mfn of the console page
+ * @return 0 on success, -1 on failure
+ */
+int xc_linux_build(xc_interface *xch,
+ uint32_t domid,
+ unsigned int mem_mb,
+ const char *image_name,
+ const char *ramdisk_name,
+ const char *cmdline,
+ const char *features,
+ unsigned long flags,
+ unsigned int store_evtchn,
+ unsigned long *store_mfn,
+ unsigned int console_evtchn,
+ unsigned long *console_mfn);
+
+/*
+ * Sets *lockfd to -1.
+ * Has deallocated everything even on error.
+ */
+int xc_suspend_evtchn_release(xc_interface *xch,
+ struct xenevtchn_handle *xce,
+ uint32_t 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,
+ struct xenevtchn_handle *xce,
+ uint32_t domid, int port, int *lockfd);
+
+/* xce must not be used for anything else */
+int xc_await_suspend(xc_interface *xch, struct xenevtchn_handle *xce,
+ int suspend_evtchn);
+
+/**
+ * The port will be signaled immediately after this call
+ * The caller should check the domain status and look for the next event
+ * On success, *lockfd will be set to >=0 and *lockfd must be preserved
+ * 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,
+ struct xenevtchn_handle *xce,
+ uint32_t domid, int port, int *lockfd);
+
+int xc_mark_page_online(xc_interface *xch, unsigned long start,
+ unsigned long end, uint32_t *status);
+
+int xc_mark_page_offline(xc_interface *xch, unsigned long start,
+ unsigned long end, uint32_t *status);
+
+int xc_query_page_offline_status(xc_interface *xch, unsigned long start,
+ unsigned long end, uint32_t *status);
+
+int xc_exchange_page(xc_interface *xch, uint32_t domid, xen_pfn_t mfn);
+
+
+/**
+ * Memory related information, such as PFN types, the P2M table,
+ * the guest word width and the guest page table levels.
+ */
+struct xc_domain_meminfo {
+ unsigned int pt_levels;
+ unsigned int guest_width;
+ xen_pfn_t *pfn_type;
+ xen_pfn_t *p2m_table;
+ unsigned long p2m_size;
+};
+
+int xc_map_domain_meminfo(xc_interface *xch, uint32_t domid,
+ struct xc_domain_meminfo *minfo);
+
+int xc_unmap_domain_meminfo(xc_interface *xch, struct xc_domain_meminfo *mem);
+
+/**
+ * This function map m2p table
+ * @parm xch a handle to an open hypervisor interface
+ * @parm max_mfn the max pfn
+ * @parm prot the flags to map, such as read/write etc
+ * @parm mfn0 return the first mfn, can be NULL
+ * @return mapped m2p table on success, NULL on failure
+ */
+xen_pfn_t *xc_map_m2p(xc_interface *xch,
+ unsigned long max_mfn,
+ int prot,
+ unsigned long *mfn0);
+#endif /* XENGUEST_H */
diff --git a/tools/libs/guest/xg_cpuid_x86.c b/tools/libs/guest/xg_cpuid_x86.c
new file mode 100644
index 0000000000..0f24d6dd08
--- /dev/null
+++ b/tools/libs/guest/xg_cpuid_x86.c
@@ -0,0 +1,665 @@
+/******************************************************************************
+ * xc_cpuid_x86.c
+ *
+ * Compute cpuid of a domain.
+ *
+ * Copyright (c) 2008, 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <limits.h>
+#include "xc_private.h"
+#include "xc_bitops.h"
+#include <xen/hvm/params.h>
+#include <xen-tools/libs.h>
+
+enum {
+#define XEN_CPUFEATURE(name, value) X86_FEATURE_##name = value,
+#include <xen/arch-x86/cpufeatureset.h>
+};
+
+#include <xen/asm/x86-vendors.h>
+
+#include <xen/lib/x86/cpu-policy.h>
+
+#define bitmaskof(idx) (1u << ((idx) & 31))
+#define featureword_of(idx) ((idx) >> 5)
+
+int xc_get_cpu_levelling_caps(xc_interface *xch, uint32_t *caps)
+{
+ DECLARE_SYSCTL;
+ int ret;
+
+ sysctl.cmd = XEN_SYSCTL_get_cpu_levelling_caps;
+ ret = do_sysctl(xch, &sysctl);
+
+ if ( !ret )
+ *caps = sysctl.u.cpu_levelling_caps.caps;
+
+ return ret;
+}
+
+int xc_get_cpu_featureset(xc_interface *xch, uint32_t index,
+ uint32_t *nr_features, uint32_t *featureset)
+{
+ DECLARE_SYSCTL;
+ DECLARE_HYPERCALL_BOUNCE(featureset,
+ *nr_features * sizeof(*featureset),
+ XC_HYPERCALL_BUFFER_BOUNCE_OUT);
+ int ret;
+
+ if ( xc_hypercall_bounce_pre(xch, featureset) )
+ return -1;
+
+ sysctl.cmd = XEN_SYSCTL_get_cpu_featureset;
+ sysctl.u.cpu_featureset.index = index;
+ sysctl.u.cpu_featureset.nr_features = *nr_features;
+ set_xen_guest_handle(sysctl.u.cpu_featureset.features, featureset);
+
+ ret = do_sysctl(xch, &sysctl);
+
+ xc_hypercall_bounce_post(xch, featureset);
+
+ if ( !ret )
+ *nr_features = sysctl.u.cpu_featureset.nr_features;
+
+ return ret;
+}
+
+uint32_t xc_get_cpu_featureset_size(void)
+{
+ return FEATURESET_NR_ENTRIES;
+}
+
+const uint32_t *xc_get_static_cpu_featuremask(
+ enum xc_static_cpu_featuremask mask)
+{
+ static const uint32_t masks[][FEATURESET_NR_ENTRIES] = {
+#define MASK(x) [XC_FEATUREMASK_ ## x] = INIT_ ## x ## _FEATURES
+
+ MASK(KNOWN),
+ MASK(SPECIAL),
+ MASK(PV_MAX),
+ MASK(PV_DEF),
+ MASK(HVM_SHADOW_MAX),
+ MASK(HVM_SHADOW_DEF),
+ MASK(HVM_HAP_MAX),
+ MASK(HVM_HAP_DEF),
+
+#undef MASK
+ };
+
+ if ( (unsigned int)mask >= ARRAY_SIZE(masks) )
+ return NULL;
+
+ return masks[mask];
+}
+
+int xc_get_cpu_policy_size(xc_interface *xch, uint32_t *nr_leaves,
+ uint32_t *nr_msrs)
+{
+ struct xen_sysctl sysctl = {};
+ int ret;
+
+ sysctl.cmd = XEN_SYSCTL_get_cpu_policy;
+
+ ret = do_sysctl(xch, &sysctl);
+
+ if ( !ret )
+ {
+ *nr_leaves = sysctl.u.cpu_policy.nr_leaves;
+ *nr_msrs = sysctl.u.cpu_policy.nr_msrs;
+ }
+
+ return ret;
+}
+
+int xc_get_system_cpu_policy(xc_interface *xch, uint32_t index,
+ uint32_t *nr_leaves, xen_cpuid_leaf_t *leaves,
+ uint32_t *nr_msrs, xen_msr_entry_t *msrs)
+{
+ struct xen_sysctl sysctl = {};
+ DECLARE_HYPERCALL_BOUNCE(leaves,
+ *nr_leaves * sizeof(*leaves),
+ XC_HYPERCALL_BUFFER_BOUNCE_OUT);
+ DECLARE_HYPERCALL_BOUNCE(msrs,
+ *nr_msrs * sizeof(*msrs),
+ XC_HYPERCALL_BUFFER_BOUNCE_OUT);
+ int ret;
+
+ if ( xc_hypercall_bounce_pre(xch, leaves) ||
+ xc_hypercall_bounce_pre(xch, msrs) )
+ return -1;
+
+ sysctl.cmd = XEN_SYSCTL_get_cpu_policy;
+ sysctl.u.cpu_policy.index = index;
+ sysctl.u.cpu_policy.nr_leaves = *nr_leaves;
+ set_xen_guest_handle(sysctl.u.cpu_policy.cpuid_policy, leaves);
+ sysctl.u.cpu_policy.nr_msrs = *nr_msrs;
+ set_xen_guest_handle(sysctl.u.cpu_policy.msr_policy, msrs);
+
+ ret = do_sysctl(xch, &sysctl);
+
+ xc_hypercall_bounce_post(xch, leaves);
+ xc_hypercall_bounce_post(xch, msrs);
+
+ if ( !ret )
+ {
+ *nr_leaves = sysctl.u.cpu_policy.nr_leaves;
+ *nr_msrs = sysctl.u.cpu_policy.nr_msrs;
+ }
+
+ return ret;
+}
+
+int xc_get_domain_cpu_policy(xc_interface *xch, uint32_t domid,
+ uint32_t *nr_leaves, xen_cpuid_leaf_t *leaves,
+ uint32_t *nr_msrs, xen_msr_entry_t *msrs)
+{
+ DECLARE_DOMCTL;
+ DECLARE_HYPERCALL_BOUNCE(leaves,
+ *nr_leaves * sizeof(*leaves),
+ XC_HYPERCALL_BUFFER_BOUNCE_OUT);
+ DECLARE_HYPERCALL_BOUNCE(msrs,
+ *nr_msrs * sizeof(*msrs),
+ XC_HYPERCALL_BUFFER_BOUNCE_OUT);
+ int ret;
+
+ if ( xc_hypercall_bounce_pre(xch, leaves) ||
+ xc_hypercall_bounce_pre(xch, msrs) )
+ return -1;
+
+ domctl.cmd = XEN_DOMCTL_get_cpu_policy;
+ domctl.domain = domid;
+ domctl.u.cpu_policy.nr_leaves = *nr_leaves;
+ set_xen_guest_handle(domctl.u.cpu_policy.cpuid_policy, leaves);
+ domctl.u.cpu_policy.nr_msrs = *nr_msrs;
+ set_xen_guest_handle(domctl.u.cpu_policy.msr_policy, msrs);
+
+ ret = do_domctl(xch, &domctl);
+
+ xc_hypercall_bounce_post(xch, leaves);
+ xc_hypercall_bounce_post(xch, msrs);
+
+ if ( !ret )
+ {
+ *nr_leaves = domctl.u.cpu_policy.nr_leaves;
+ *nr_msrs = domctl.u.cpu_policy.nr_msrs;
+ }
+
+ return ret;
+}
+
+int xc_set_domain_cpu_policy(xc_interface *xch, uint32_t domid,
+ uint32_t nr_leaves, xen_cpuid_leaf_t *leaves,
+ uint32_t nr_msrs, xen_msr_entry_t *msrs,
+ uint32_t *err_leaf_p, uint32_t *err_subleaf_p,
+ uint32_t *err_msr_p)
+{
+ DECLARE_DOMCTL;
+ DECLARE_HYPERCALL_BOUNCE(leaves,
+ nr_leaves * sizeof(*leaves),
+ XC_HYPERCALL_BUFFER_BOUNCE_IN);
+ DECLARE_HYPERCALL_BOUNCE(msrs,
+ nr_msrs * sizeof(*msrs),
+ XC_HYPERCALL_BUFFER_BOUNCE_IN);
+ int ret;
+
+ if ( err_leaf_p )
+ *err_leaf_p = -1;
+ if ( err_subleaf_p )
+ *err_subleaf_p = -1;
+ if ( err_msr_p )
+ *err_msr_p = -1;
+
+ if ( xc_hypercall_bounce_pre(xch, leaves) )
+ return -1;
+
+ if ( xc_hypercall_bounce_pre(xch, msrs) )
+ return -1;
+
+ domctl.cmd = XEN_DOMCTL_set_cpu_policy;
+ domctl.domain = domid;
+ domctl.u.cpu_policy.nr_leaves = nr_leaves;
+ set_xen_guest_handle(domctl.u.cpu_policy.cpuid_policy, leaves);
+ domctl.u.cpu_policy.nr_msrs = nr_msrs;
+ set_xen_guest_handle(domctl.u.cpu_policy.msr_policy, msrs);
+ domctl.u.cpu_policy.err_leaf = -1;
+ domctl.u.cpu_policy.err_subleaf = -1;
+ domctl.u.cpu_policy.err_msr = -1;
+
+ ret = do_domctl(xch, &domctl);
+
+ xc_hypercall_bounce_post(xch, leaves);
+ xc_hypercall_bounce_post(xch, msrs);
+
+ if ( err_leaf_p )
+ *err_leaf_p = domctl.u.cpu_policy.err_leaf;
+ if ( err_subleaf_p )
+ *err_subleaf_p = domctl.u.cpu_policy.err_subleaf;
+ if ( err_msr_p )
+ *err_msr_p = domctl.u.cpu_policy.err_msr;
+
+ return ret;
+}
+
+static int compare_leaves(const void *l, const void *r)
+{
+ const xen_cpuid_leaf_t *lhs = l;
+ const xen_cpuid_leaf_t *rhs = r;
+
+ if ( lhs->leaf != rhs->leaf )
+ return lhs->leaf < rhs->leaf ? -1 : 1;
+
+ if ( lhs->subleaf != rhs->subleaf )
+ return lhs->subleaf < rhs->subleaf ? -1 : 1;
+
+ return 0;
+}
+
+static xen_cpuid_leaf_t *find_leaf(
+ xen_cpuid_leaf_t *leaves, unsigned int nr_leaves,
+ const struct xc_xend_cpuid *xend)
+{
+ const xen_cpuid_leaf_t key = { xend->leaf, xend->subleaf };
+
+ return bsearch(&key, leaves, nr_leaves, sizeof(*leaves), compare_leaves);
+}
+
+static int xc_cpuid_xend_policy(
+ xc_interface *xch, uint32_t domid, const struct xc_xend_cpuid *xend)
+{
+ int rc;
+ xc_dominfo_t di;
+ unsigned int nr_leaves, nr_msrs;
+ uint32_t err_leaf = -1, err_subleaf = -1, err_msr = -1;
+ /*
+ * Three full policies. The host, domain max, and domain current for the
+ * domain type.
+ */
+ xen_cpuid_leaf_t *host = NULL, *max = NULL, *cur = NULL;
+ unsigned int nr_host, nr_max, nr_cur;
+
+ if ( xc_domain_getinfo(xch, domid, 1, &di) != 1 ||
+ di.domid != domid )
+ {
+ ERROR("Failed to obtain d%d info", domid);
+ rc = -ESRCH;
+ goto fail;
+ }
+
+ rc = xc_get_cpu_policy_size(xch, &nr_leaves, &nr_msrs);
+ if ( rc )
+ {
+ PERROR("Failed to obtain policy info size");
+ rc = -errno;
+ goto fail;
+ }
+
+ rc = -ENOMEM;
+ if ( (host = calloc(nr_leaves, sizeof(*host))) == NULL ||
+ (max = calloc(nr_leaves, sizeof(*max))) == NULL ||
+ (cur = calloc(nr_leaves, sizeof(*cur))) == NULL )
+ {
+ ERROR("Unable to allocate memory for %u CPUID leaves", nr_leaves);
+ goto fail;
+ }
+
+ /* Get the domain's current policy. */
+ nr_msrs = 0;
+ nr_cur = nr_leaves;
+ rc = xc_get_domain_cpu_policy(xch, domid, &nr_cur, cur, &nr_msrs, NULL);
+ if ( rc )
+ {
+ PERROR("Failed to obtain d%d current policy", domid);
+ rc = -errno;
+ goto fail;
+ }
+
+ /* Get the domain's max policy. */
+ nr_msrs = 0;
+ nr_max = nr_leaves;
+ rc = xc_get_system_cpu_policy(xch, di.hvm ? XEN_SYSCTL_cpu_policy_hvm_max
+ : XEN_SYSCTL_cpu_policy_pv_max,
+ &nr_max, max, &nr_msrs, NULL);
+ if ( rc )
+ {
+ PERROR("Failed to obtain %s max policy", di.hvm ? "hvm" : "pv");
+ rc = -errno;
+ goto fail;
+ }
+
+ /* Get the host policy. */
+ nr_msrs = 0;
+ nr_host = nr_leaves;
+ rc = xc_get_system_cpu_policy(xch, XEN_SYSCTL_cpu_policy_host,
+ &nr_host, host, &nr_msrs, NULL);
+ if ( rc )
+ {
+ PERROR("Failed to obtain host policy");
+ rc = -errno;
+ goto fail;
+ }
+
+ rc = -EINVAL;
+ for ( ; xend->leaf != XEN_CPUID_INPUT_UNUSED; ++xend )
+ {
+ xen_cpuid_leaf_t *cur_leaf = find_leaf(cur, nr_cur, xend);
+ const xen_cpuid_leaf_t *max_leaf = find_leaf(max, nr_max, xend);
+ const xen_cpuid_leaf_t *host_leaf = find_leaf(host, nr_host, xend);
+
+ if ( cur_leaf == NULL || max_leaf == NULL || host_leaf == NULL )
+ {
+ ERROR("Missing leaf %#x, subleaf %#x", xend->leaf, xend->subleaf);
+ goto fail;
+ }
+
+ for ( unsigned int i = 0; i < ARRAY_SIZE(xend->policy); i++ )
+ {
+ uint32_t *cur_reg = &cur_leaf->a + i;
+ const uint32_t *max_reg = &max_leaf->a + i;
+ const uint32_t *host_reg = &host_leaf->a + i;
+
+ if ( xend->policy[i] == NULL )
+ continue;
+
+ for ( unsigned int j = 0; j < 32; j++ )
+ {
+ bool val;
+
+ if ( xend->policy[i][j] == '1' )
+ val = true;
+ else if ( xend->policy[i][j] == '0' )
+ val = false;
+ else if ( xend->policy[i][j] == 'x' )
+ val = test_bit(31 - j, max_reg);
+ else if ( xend->policy[i][j] == 'k' ||
+ xend->policy[i][j] == 's' )
+ val = test_bit(31 - j, host_reg);
+ else
+ {
+ ERROR("Bad character '%c' in policy[%d] string '%s'",
+ xend->policy[i][j], i, xend->policy[i]);
+ goto fail;
+ }
+
+ clear_bit(31 - j, cur_reg);
+ if ( val )
+ set_bit(31 - j, cur_reg);
+ }
+ }
+ }
+
+ /* Feed the transformed currrent policy back up to Xen. */
+ rc = xc_set_domain_cpu_policy(xch, domid, nr_cur, cur, 0, NULL,
+ &err_leaf, &err_subleaf, &err_msr);
+ if ( rc )
+ {
+ PERROR("Failed to set d%d's policy (err leaf %#x, subleaf %#x, msr
%#x)",
+ domid, err_leaf, err_subleaf, err_msr);
+ rc = -errno;
+ goto fail;
+ }
+
+ /* Success! */
+
+ fail:
+ free(cur);
+ free(max);
+ free(host);
+
+ return rc;
+}
+
+int xc_cpuid_apply_policy(xc_interface *xch, uint32_t domid, bool restore,
+ const uint32_t *featureset, unsigned int nr_features,
+ bool pae,
+ const struct xc_xend_cpuid *xend)
+{
+ int rc;
+ xc_dominfo_t di;
+ unsigned int i, nr_leaves, nr_msrs;
+ xen_cpuid_leaf_t *leaves = NULL;
+ struct cpuid_policy *p = NULL;
+ uint32_t err_leaf = -1, err_subleaf = -1, err_msr = -1;
+ uint32_t host_featureset[FEATURESET_NR_ENTRIES] = {};
+ uint32_t len = ARRAY_SIZE(host_featureset);
+
+ if ( xc_domain_getinfo(xch, domid, 1, &di) != 1 ||
+ di.domid != domid )
+ {
+ ERROR("Failed to obtain d%d info", domid);
+ rc = -ESRCH;
+ goto out;
+ }
+
+ rc = xc_get_cpu_policy_size(xch, &nr_leaves, &nr_msrs);
+ if ( rc )
+ {
+ PERROR("Failed to obtain policy info size");
+ rc = -errno;
+ goto out;
+ }
+
+ rc = -ENOMEM;
+ if ( (leaves = calloc(nr_leaves, sizeof(*leaves))) == NULL ||
+ (p = calloc(1, sizeof(*p))) == NULL )
+ goto out;
+
+ /* Get the host policy. */
+ rc = xc_get_cpu_featureset(xch, XEN_SYSCTL_cpu_featureset_host,
+ &len, host_featureset);
+ if ( rc )
+ {
+ /* Tolerate "buffer too small", as we've got the bits we need. */
+ if ( errno == ENOBUFS )
+ rc = 0;
+ else
+ {
+ PERROR("Failed to obtain host featureset");
+ rc = -errno;
+ goto out;
+ }
+ }
+
+ /* Get the domain's default policy. */
+ nr_msrs = 0;
+ rc = xc_get_system_cpu_policy(xch, di.hvm ?
XEN_SYSCTL_cpu_policy_hvm_default
+ :
XEN_SYSCTL_cpu_policy_pv_default,
+ &nr_leaves, leaves, &nr_msrs, NULL);
+ if ( rc )
+ {
+ PERROR("Failed to obtain %s default policy", di.hvm ? "hvm" : "pv");
+ rc = -errno;
+ goto out;
+ }
+
+ rc = x86_cpuid_copy_from_buffer(p, leaves, nr_leaves,
+ &err_leaf, &err_subleaf);
+ if ( rc )
+ {
+ ERROR("Failed to deserialise CPUID (err leaf %#x, subleaf %#x) (%d =
%s)",
+ err_leaf, err_subleaf, -rc, strerror(-rc));
+ goto out;
+ }
+
+ /*
+ * Account for feature which have been disabled by default since Xen 4.13,
+ * so migrated-in VM's don't risk seeing features disappearing.
+ */
+ if ( restore )
+ {
+ p->basic.rdrand = test_bit(X86_FEATURE_RDRAND, host_featureset);
+
+ if ( di.hvm )
+ {
+ p->feat.mpx = test_bit(X86_FEATURE_MPX, host_featureset);
+ }
+ }
+
+ if ( featureset )
+ {
+ uint32_t disabled_features[FEATURESET_NR_ENTRIES],
+ feat[FEATURESET_NR_ENTRIES] = {};
+ static const uint32_t deep_features[] = INIT_DEEP_FEATURES;
+ unsigned int i, b;
+
+ /*
+ * The user supplied featureset may be shorter or longer than
+ * FEATURESET_NR_ENTRIES. Shorter is fine, and we will zero-extend.
+ * Longer is fine, so long as it only padded with zeros.
+ */
+ unsigned int user_len = min(FEATURESET_NR_ENTRIES + 0u, nr_features);
+
+ /* Check for truncated set bits. */
+ rc = -EOPNOTSUPP;
+ for ( i = user_len; i < nr_features; ++i )
+ if ( featureset[i] != 0 )
+ goto out;
+
+ memcpy(feat, featureset, sizeof(*featureset) * user_len);
+
+ /* Disable deep dependencies of disabled features. */
+ for ( i = 0; i < ARRAY_SIZE(disabled_features); ++i )
+ disabled_features[i] = ~feat[i] & deep_features[i];
+
+ for ( b = 0; b < sizeof(disabled_features) * CHAR_BIT; ++b )
+ {
+ const uint32_t *dfs;
+
+ if ( !test_bit(b, disabled_features) ||
+ !(dfs = x86_cpuid_lookup_deep_deps(b)) )
+ continue;
+
+ for ( i = 0; i < ARRAY_SIZE(disabled_features); ++i )
+ {
+ feat[i] &= ~dfs[i];
+ disabled_features[i] &= ~dfs[i];
+ }
+ }
+
+ cpuid_featureset_to_policy(feat, p);
+ }
+ else
+ {
+ if ( di.hvm )
+ p->basic.pae = pae;
+ }
+
+ if ( !di.hvm )
+ {
+ /*
+ * On hardware without CPUID Faulting, PV guests see real topology.
+ * As a consequence, they also need to see the host htt/cmp fields.
+ */
+ p->basic.htt = test_bit(X86_FEATURE_HTT, host_featureset);
+ p->extd.cmp_legacy = test_bit(X86_FEATURE_CMP_LEGACY, host_featureset);
+ }
+ else
+ {
+ /*
+ * Topology for HVM guests is entirely controlled by Xen. For now, we
+ * hardcode APIC_ID = vcpu_id * 2 to give the illusion of no SMT.
+ */
+ p->basic.htt = true;
+ p->extd.cmp_legacy = false;
+
+ /*
+ * Leaf 1 EBX[23:16] is Maximum Logical Processors Per Package.
+ * Update to reflect vLAPIC_ID = vCPU_ID * 2, but make sure to avoid
+ * overflow.
+ */
+ if ( !(p->basic.lppp & 0x80) )
+ p->basic.lppp *= 2;
+
+ switch ( p->x86_vendor )
+ {
+ case X86_VENDOR_INTEL:
+ for ( i = 0; (p->cache.subleaf[i].type &&
+ i < ARRAY_SIZE(p->cache.raw)); ++i )
+ {
+ p->cache.subleaf[i].cores_per_package =
+ (p->cache.subleaf[i].cores_per_package << 1) | 1;
+ p->cache.subleaf[i].threads_per_cache = 0;
+ }
+ break;
+
+ case X86_VENDOR_AMD:
+ case X86_VENDOR_HYGON:
+ /*
+ * Leaf 0x80000008 ECX[15:12] is ApicIdCoreSize.
+ * Leaf 0x80000008 ECX[7:0] is NumberOfCores (minus one).
+ * Update to reflect vLAPIC_ID = vCPU_ID * 2. But avoid
+ * - overflow,
+ * - going out of sync with leaf 1 EBX[23:16],
+ * - incrementing ApicIdCoreSize when it's zero (which changes the
+ * meaning of bits 7:0).
+ *
+ * UPDATE: I addition to avoiding overflow, some
+ * proprietary operating systems have trouble with
+ * apic_id_size values greater than 7. Limit the value to
+ * 7 for now.
+ */
+ if ( p->extd.nc < 0x7f )
+ {
+ if ( p->extd.apic_id_size != 0 && p->extd.apic_id_size < 0x7 )
+ p->extd.apic_id_size++;
+
+ p->extd.nc = (p->extd.nc << 1) | 1;
+ }
+ break;
+ }
+
+ /*
+ * These settings are necessary to cause earlier HVM_PARAM_NESTEDHVM /
+ * XEN_DOMCTL_disable_migrate settings to be reflected correctly in
+ * CPUID. Xen will discard these bits if configuration hasn't been
+ * set for the domain.
+ */
+ p->extd.itsc = true;
+ p->basic.vmx = true;
+ p->extd.svm = true;
+ }
+
+ rc = x86_cpuid_copy_to_buffer(p, leaves, &nr_leaves);
+ if ( rc )
+ {
+ ERROR("Failed to serialise CPUID (%d = %s)", -rc, strerror(-rc));
+ goto out;
+ }
+
+ rc = xc_set_domain_cpu_policy(xch, domid, nr_leaves, leaves, 0, NULL,
+ &err_leaf, &err_subleaf, &err_msr);
+ if ( rc )
+ {
+ PERROR("Failed to set d%d's policy (err leaf %#x, subleaf %#x, msr
%#x)",
+ domid, err_leaf, err_subleaf, err_msr);
+ rc = -errno;
+ goto out;
+ }
+
+ if ( xend && (rc = xc_cpuid_xend_policy(xch, domid, xend)) )
+ goto out;
+
+ rc = 0;
+
+out:
+ free(p);
+ free(leaves);
+
+ return rc;
+}
diff --git a/tools/libs/guest/xg_dom_arm.c b/tools/libs/guest/xg_dom_arm.c
new file mode 100644
index 0000000000..3f66f1d890
--- /dev/null
+++ b/tools/libs/guest/xg_dom_arm.c
@@ -0,0 +1,552 @@
+/*
+ * Xen domain builder -- ARM
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Copyright (c) 2011, Citrix Systems
+ */
+#include <inttypes.h>
+#include <assert.h>
+
+#include <xen/xen.h>
+#include <xen/io/protocols.h>
+#include <xen-tools/libs.h>
+
+#include "xg_private.h"
+#include "xenctrl_dom.h"
+
+#define NR_MAGIC_PAGES 4
+#define CONSOLE_PFN_OFFSET 0
+#define XENSTORE_PFN_OFFSET 1
+#define MEMACCESS_PFN_OFFSET 2
+#define VUART_PFN_OFFSET 3
+
+#define LPAE_SHIFT 9
+
+#define PFN_4K_SHIFT (0)
+#define PFN_2M_SHIFT (PFN_4K_SHIFT+LPAE_SHIFT)
+#define PFN_1G_SHIFT (PFN_2M_SHIFT+LPAE_SHIFT)
+#define PFN_512G_SHIFT (PFN_1G_SHIFT+LPAE_SHIFT)
+
+/* get guest IO ABI protocol */
+const char *xc_domain_get_native_protocol(xc_interface *xch,
+ uint32_t domid)
+{
+ return XEN_IO_PROTO_ABI_ARM;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int alloc_magic_pages(struct xc_dom_image *dom)
+{
+ int rc, i;
+ const xen_pfn_t base = GUEST_MAGIC_BASE >> XC_PAGE_SHIFT;
+ xen_pfn_t p2m[NR_MAGIC_PAGES];
+
+ BUILD_BUG_ON(NR_MAGIC_PAGES > GUEST_MAGIC_SIZE >> XC_PAGE_SHIFT);
+
+ DOMPRINTF_CALLED(dom->xch);
+
+ for (i = 0; i < NR_MAGIC_PAGES; i++)
+ p2m[i] = base + i;
+
+ rc = xc_domain_populate_physmap_exact(
+ dom->xch, dom->guest_domid, NR_MAGIC_PAGES,
+ 0, 0, p2m);
+ if ( rc < 0 )
+ return rc;
+
+ dom->console_pfn = base + CONSOLE_PFN_OFFSET;
+ dom->xenstore_pfn = base + XENSTORE_PFN_OFFSET;
+ dom->vuart_gfn = base + VUART_PFN_OFFSET;
+
+ xc_clear_domain_page(dom->xch, dom->guest_domid, dom->console_pfn);
+ xc_clear_domain_page(dom->xch, dom->guest_domid, dom->xenstore_pfn);
+ xc_clear_domain_page(dom->xch, dom->guest_domid, base +
MEMACCESS_PFN_OFFSET);
+ xc_clear_domain_page(dom->xch, dom->guest_domid, dom->vuart_gfn);
+
+ xc_hvm_param_set(dom->xch, dom->guest_domid, HVM_PARAM_CONSOLE_PFN,
+ dom->console_pfn);
+ xc_hvm_param_set(dom->xch, dom->guest_domid, HVM_PARAM_STORE_PFN,
+ dom->xenstore_pfn);
+ xc_hvm_param_set(dom->xch, dom->guest_domid, HVM_PARAM_MONITOR_RING_PFN,
+ base + MEMACCESS_PFN_OFFSET);
+ /* allocated by toolstack */
+ xc_hvm_param_set(dom->xch, dom->guest_domid, HVM_PARAM_CONSOLE_EVTCHN,
+ dom->console_evtchn);
+ xc_hvm_param_set(dom->xch, dom->guest_domid, HVM_PARAM_STORE_EVTCHN,
+ dom->xenstore_evtchn);
+
+ return 0;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int start_info_arm(struct xc_dom_image *dom)
+{
+ DOMPRINTF_CALLED(dom->xch);
+ return 0;
+}
+
+static int shared_info_arm(struct xc_dom_image *dom, void *ptr)
+{
+ DOMPRINTF_CALLED(dom->xch);
+ return 0;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int vcpu_arm32(struct xc_dom_image *dom)
+{
+ vcpu_guest_context_any_t any_ctx;
+ vcpu_guest_context_t *ctxt = &any_ctx.c;
+ int rc;
+
+ DOMPRINTF_CALLED(dom->xch);
+
+ /* clear everything */
+ memset(ctxt, 0, sizeof(*ctxt));
+
+ ctxt->user_regs.pc32 = dom->parms.virt_entry;
+
+ /* Linux boot protocol. See linux.Documentation/arm/Booting. */
+ ctxt->user_regs.r0_usr = 0; /* SBZ */
+ /* Machine ID: We use DTB therefore no machine id */
+ ctxt->user_regs.r1_usr = 0xffffffff;
+ /* ATAGS/DTB: We currently require that the guest kernel to be
+ * using CONFIG_ARM_APPENDED_DTB. Ensure that r2 does not look
+ * like a valid pointer to a set of ATAGS or a DTB.
+ */
+ ctxt->user_regs.r2_usr = dom->devicetree_blob ?
+ dom->devicetree_seg.vstart : 0xffffffff;
+
+ ctxt->sctlr = SCTLR_GUEST_INIT;
+
+ ctxt->ttbr0 = 0;
+ ctxt->ttbr1 = 0;
+ ctxt->ttbcr = 0; /* Defined Reset Value */
+
+ ctxt->user_regs.cpsr = PSR_GUEST32_INIT;
+
+ ctxt->flags = VGCF_online;
+
+ DOMPRINTF("Initial state CPSR %#"PRIx32" PC %#"PRIx32,
+ ctxt->user_regs.cpsr, ctxt->user_regs.pc32);
+
+ rc = xc_vcpu_setcontext(dom->xch, dom->guest_domid, 0, &any_ctx);
+ if ( rc != 0 )
+ xc_dom_panic(dom->xch, XC_INTERNAL_ERROR,
+ "%s: SETVCPUCONTEXT failed (rc=%d)", __func__, rc);
+
+ return rc;
+}
+
+static int vcpu_arm64(struct xc_dom_image *dom)
+{
+ vcpu_guest_context_any_t any_ctx;
+ vcpu_guest_context_t *ctxt = &any_ctx.c;
+ int rc;
+
+ DOMPRINTF_CALLED(dom->xch);
+ /* clear everything */
+ memset(ctxt, 0, sizeof(*ctxt));
+
+ ctxt->user_regs.pc64 = dom->parms.virt_entry;
+
+ /* Linux boot protocol. See linux.Documentation/arm64/booting.txt. */
+ ctxt->user_regs.x0 = dom->devicetree_blob ?
+ dom->devicetree_seg.vstart : 0xffffffff;
+ ctxt->user_regs.x1 = 0;
+ ctxt->user_regs.x2 = 0;
+ ctxt->user_regs.x3 = 0;
+
+ DOMPRINTF("DTB %"PRIx64, ctxt->user_regs.x0);
+
+ ctxt->sctlr = SCTLR_GUEST_INIT;
+
+ ctxt->ttbr0 = 0;
+ ctxt->ttbr1 = 0;
+ ctxt->ttbcr = 0; /* Defined Reset Value */
+
+ ctxt->user_regs.cpsr = PSR_GUEST64_INIT;
+
+ ctxt->flags = VGCF_online;
+
+ DOMPRINTF("Initial state CPSR %#"PRIx32" PC %#"PRIx64,
+ ctxt->user_regs.cpsr, ctxt->user_regs.pc64);
+
+ rc = xc_vcpu_setcontext(dom->xch, dom->guest_domid, 0, &any_ctx);
+ if ( rc != 0 )
+ xc_dom_panic(dom->xch, XC_INTERNAL_ERROR,
+ "%s: SETVCPUCONTEXT failed (rc=%d)", __func__, rc);
+
+ return rc;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int set_mode(xc_interface *xch, uint32_t domid, char *guest_type)
+{
+ static const struct {
+ char *guest;
+ uint32_t size;
+ } types[] = {
+ { "xen-3.0-aarch64", 64 },
+ { "xen-3.0-armv7l", 32 },
+ };
+ DECLARE_DOMCTL;
+ int i,rc;
+
+ domctl.domain = domid;
+ domctl.cmd = XEN_DOMCTL_set_address_size;
+ domctl.u.address_size.size = 0;
+
+ for ( i = 0; i < ARRAY_SIZE(types); i++ )
+ if ( !strcmp(types[i].guest, guest_type) )
+ domctl.u.address_size.size = types[i].size;
+ if ( domctl.u.address_size.size == 0 )
+ {
+ xc_dom_printf(xch, "%s: warning: unknown guest type %s",
+ __FUNCTION__, guest_type);
+ return -EINVAL;
+ }
+
+ xc_dom_printf(xch, "%s: guest %s, address size %" PRId32 "", __FUNCTION__,
+ guest_type, domctl.u.address_size.size);
+ rc = do_domctl(xch, &domctl);
+ if ( rc != 0 )
+ xc_dom_printf(xch, "%s: warning: failed (rc=%d)",
+ __FUNCTION__, rc);
+ return rc;
+}
+
+/* >0: success, *nr_pfns set to number actually populated
+ * 0: didn't try with this pfn shift (e.g. misaligned base etc)
+ * <0: ERROR
+ */
+static int populate_one_size(struct xc_dom_image *dom, int pfn_shift,
+ xen_pfn_t base_pfn, xen_pfn_t *nr_pfns,
+ xen_pfn_t *extents)
+{
+ /* The mask for this level */
+ const uint64_t mask = ((uint64_t)1<<(pfn_shift))-1;
+ /* The shift, mask and next boundary for the level above this one */
+ const int next_shift = pfn_shift + LPAE_SHIFT;
+ const uint64_t next_mask = ((uint64_t)1<<next_shift)-1;
+ const xen_pfn_t next_boundary
+ = (base_pfn + ((uint64_t)1<<next_shift)) & ~next_mask;
+
+ int nr, i, count;
+ xen_pfn_t end_pfn = base_pfn + *nr_pfns;
+
+ /* No level zero super pages with current hardware */
+ if ( pfn_shift == PFN_512G_SHIFT )
+ return 0;
+
+ /* base is misaligned for this level */
+ if ( mask & base_pfn )
+ return 0;
+
+ /*
+ * If base is not aligned at the next level up then try and make
+ * it so for next time around.
+ */
+ if ( (base_pfn & next_mask) && end_pfn > next_boundary )
+ end_pfn = next_boundary;
+
+ count = ( end_pfn - base_pfn ) >> pfn_shift;
+
+ /* Nothing to allocate */
+ if ( !count )
+ return 0;
+
+ for ( i = 0 ; i < count ; i ++ )
+ extents[i] = base_pfn + (i<<pfn_shift);
+
+ nr = xc_domain_populate_physmap(dom->xch, dom->guest_domid, count,
+ pfn_shift, 0, extents);
+ if ( nr <= 0 ) return nr;
+ DOMPRINTF("%s: populated %#x/%#x entries with shift %d",
+ __FUNCTION__, nr, count, pfn_shift);
+
+ *nr_pfns = nr << pfn_shift;
+
+ return 1;
+}
+
+static int populate_guest_memory(struct xc_dom_image *dom,
+ xen_pfn_t base_pfn, xen_pfn_t nr_pfns)
+{
+ int rc = 0;
+ xen_pfn_t allocsz, pfn, *extents;
+
+ extents = calloc(1024*1024,sizeof(xen_pfn_t));
+ if ( extents == NULL )
+ {
+ DOMPRINTF("%s: Unable to allocate extent array", __FUNCTION__);
+ return -1;
+ }
+
+ DOMPRINTF("%s: populating RAM @ %016"PRIx64"-%016"PRIx64" (%"PRId64"MB)",
+ __FUNCTION__,
+ (uint64_t)base_pfn << XC_PAGE_SHIFT,
+ (uint64_t)(base_pfn + nr_pfns) << XC_PAGE_SHIFT,
+ (uint64_t)nr_pfns >> (20-XC_PAGE_SHIFT));
+
+ for ( pfn = 0; pfn < nr_pfns; pfn += allocsz )
+ {
+ allocsz = min_t(int, 1024*1024, nr_pfns - pfn);
+#if 0 /* Enable this to exercise/debug the code which tries to realign
+ * to a superpage boundary, by misaligning at the start. */
+ if ( pfn == 0 )
+ {
+ allocsz = 1;
+ rc = populate_one_size(dom, PFN_4K_SHIFT,
+ base_pfn + pfn, &allocsz, extents);
+ if (rc < 0) break;
+ if (rc > 0) continue;
+ /* Failed to allocate a single page? */
+ break;
+ }
+#endif
+
+ rc = populate_one_size(dom, PFN_512G_SHIFT,
+ base_pfn + pfn, &allocsz, extents);
+ if ( rc < 0 ) break;
+ if ( rc > 0 ) continue;
+
+ rc = populate_one_size(dom, PFN_1G_SHIFT,
+ base_pfn + pfn, &allocsz, extents);
+ if ( rc < 0 ) break;
+ if ( rc > 0 ) continue;
+
+ rc = populate_one_size(dom, PFN_2M_SHIFT,
+ base_pfn + pfn, &allocsz, extents);
+ if ( rc < 0 ) break;
+ if ( rc > 0 ) continue;
+
+ rc = populate_one_size(dom, PFN_4K_SHIFT,
+ base_pfn + pfn, &allocsz, extents);
+ if ( rc < 0 ) break;
+ if ( rc == 0 )
+ {
+ DOMPRINTF("%s: Not enough RAM", __FUNCTION__);
+ errno = ENOMEM;
+ rc = -1;
+ goto out;
+ }
+ }
+
+out:
+ free(extents);
+ return rc < 0 ? rc : 0;
+}
+
+static int meminit(struct xc_dom_image *dom)
+{
+ int i, rc;
+ uint64_t modbase;
+
+ uint64_t ramsize = (uint64_t)dom->total_pages << XC_PAGE_SHIFT;
+
+ const uint64_t bankbase[] = GUEST_RAM_BANK_BASES;
+ const uint64_t bankmax[] = GUEST_RAM_BANK_SIZES;
+
+ /* Convenient */
+ const uint64_t kernbase = dom->kernel_seg.vstart;
+ const uint64_t kernend = ROUNDUP(dom->kernel_seg.vend, 21/*2MB*/);
+ const uint64_t kernsize = kernend - kernbase;
+ const uint64_t dtb_size = dom->devicetree_blob ?
+ ROUNDUP(dom->devicetree_size, XC_PAGE_SHIFT) : 0;
+ const uint64_t ramdisk_size = dom->modules[0].blob ?
+ ROUNDUP(dom->modules[0].size, XC_PAGE_SHIFT) : 0;
+ const uint64_t modsize = dtb_size + ramdisk_size;
+ const uint64_t ram128mb = bankbase[0] + (128<<20);
+
+ xen_pfn_t p2m_size;
+ uint64_t bank0end;
+
+ assert(dom->rambase_pfn << XC_PAGE_SHIFT == bankbase[0]);
+
+ if ( modsize + kernsize > bankmax[0] )
+ {
+ DOMPRINTF("%s: Not enough memory for the kernel+dtb+initrd",
+ __FUNCTION__);
+ return -1;
+ }
+
+ if ( ramsize == 0 )
+ {
+ DOMPRINTF("%s: ram size is 0", __FUNCTION__);
+ return -1;
+ }
+
+ if ( ramsize > GUEST_RAM_MAX )
+ {
+ DOMPRINTF("%s: ram size is too large for guest address space: "
+ "%"PRIx64" > %llx",
+ __FUNCTION__, ramsize, GUEST_RAM_MAX);
+ return -1;
+ }
+
+ rc = set_mode(dom->xch, dom->guest_domid, dom->guest_type);
+ if ( rc )
+ return rc;
+
+ for ( i = 0; ramsize && i < GUEST_RAM_BANKS; i++ )
+ {
+ uint64_t banksize = ramsize > bankmax[i] ? bankmax[i] : ramsize;
+
+ ramsize -= banksize;
+
+ p2m_size = ( bankbase[i] + banksize - bankbase[0] ) >> XC_PAGE_SHIFT;
+
+ dom->rambank_size[i] = banksize >> XC_PAGE_SHIFT;
+ }
+
+ assert(dom->rambank_size[0] != 0);
+ assert(ramsize == 0); /* Too much RAM is rejected above */
+
+ dom->p2m_size = p2m_size;
+
+ /* setup initial p2m and allocate guest memory */
+ for ( i = 0; i < GUEST_RAM_BANKS && dom->rambank_size[i]; i++ )
+ {
+ if ((rc = populate_guest_memory(dom,
+ bankbase[i] >> XC_PAGE_SHIFT,
+ dom->rambank_size[i])))
+ return rc;
+ }
+
+ /*
+ * We try to place dtb+initrd at 128MB or if we have less RAM
+ * as high as possible. If there is no space then fallback to
+ * just before the kernel.
+ *
+ * If changing this then consider
+ * xen/arch/arm/kernel.c:place_modules as well.
+ */
+ bank0end = bankbase[0] + ((uint64_t)dom->rambank_size[0] << XC_PAGE_SHIFT);
+
+ if ( bank0end >= ram128mb + modsize && kernend < ram128mb )
+ modbase = ram128mb;
+ else if ( bank0end - modsize > kernend )
+ modbase = bank0end - modsize;
+ else if (kernbase - bankbase[0] > modsize )
+ modbase = kernbase - modsize;
+ else
+ return -1;
+
+ DOMPRINTF("%s: placing boot modules at 0x%" PRIx64, __FUNCTION__, modbase);
+
+ /*
+ * Must map DTB *after* initrd, to satisfy order of calls to
+ * xc_dom_alloc_segment in xc_dom_build_image, which must map
+ * things at monotonolically increasing addresses.
+ */
+ if ( ramdisk_size )
+ {
+ dom->modules[0].seg.vstart = modbase;
+ dom->modules[0].seg.vend = modbase + ramdisk_size;
+
+ DOMPRINTF("%s: ramdisk: 0x%" PRIx64 " -> 0x%" PRIx64 "",
+ __FUNCTION__,
+ dom->modules[0].seg.vstart, dom->modules[0].seg.vend);
+
+ modbase += ramdisk_size;
+ }
+
+ if ( dtb_size )
+ {
+ dom->devicetree_seg.vstart = modbase;
+ dom->devicetree_seg.vend = modbase + dtb_size;
+
+ DOMPRINTF("%s: devicetree: 0x%" PRIx64 " -> 0x%" PRIx64 "",
+ __FUNCTION__,
+ dom->devicetree_seg.vstart, dom->devicetree_seg.vend);
+
+ modbase += dtb_size;
+ }
+
+ return 0;
+}
+
+bool xc_dom_translated(const struct xc_dom_image *dom)
+{
+ return true;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int bootearly(struct xc_dom_image *dom)
+{
+ DOMPRINTF("%s: doing nothing", __FUNCTION__);
+ return 0;
+}
+
+static int bootlate(struct xc_dom_image *dom)
+{
+ /* XXX
+ * map shared info
+ * map grant tables
+ * setup shared info
+ */
+ return 0;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static struct xc_dom_arch xc_dom_32 = {
+ .guest_type = "xen-3.0-armv7l",
+ .native_protocol = XEN_IO_PROTO_ABI_ARM,
+ .page_shift = PAGE_SHIFT_ARM,
+ .sizeof_pfn = 8,
+ .alloc_magic_pages = alloc_magic_pages,
+ .start_info = start_info_arm,
+ .shared_info = shared_info_arm,
+ .vcpu = vcpu_arm32,
+ .meminit = meminit,
+ .bootearly = bootearly,
+ .bootlate = bootlate,
+};
+
+static struct xc_dom_arch xc_dom_64 = {
+ .guest_type = "xen-3.0-aarch64",
+ .native_protocol = XEN_IO_PROTO_ABI_ARM,
+ .page_shift = PAGE_SHIFT_ARM,
+ .sizeof_pfn = 8,
+ .alloc_magic_pages = alloc_magic_pages,
+ .start_info = start_info_arm,
+ .shared_info = shared_info_arm,
+ .vcpu = vcpu_arm64,
+ .meminit = meminit,
+ .bootearly = bootearly,
+ .bootlate = bootlate,
+};
+
+static void __init register_arch_hooks(void)
+{
+ xc_dom_register_arch_hooks(&xc_dom_32);
+ xc_dom_register_arch_hooks(&xc_dom_64);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libs/guest/xg_dom_armzimageloader.c
b/tools/libs/guest/xg_dom_armzimageloader.c
new file mode 100644
index 0000000000..4246c8e5fa
--- /dev/null
+++ b/tools/libs/guest/xg_dom_armzimageloader.c
@@ -0,0 +1,271 @@
+/*
+ * Xen domain builder -- ARM zImage bits
+ *
+ * Parse and load ARM zImage kernel images.
+ *
+ * Copyright (C) 2012, Citrix Systems.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+
+#include "xg_private.h"
+#include "xenctrl_dom.h"
+
+#include <arpa/inet.h> /* XXX ntohl is not the right function... */
+
+struct minimal_dtb_header {
+ uint32_t magic;
+ uint32_t total_size;
+ /* There are other fields but we don't use them yet. */
+};
+
+#define DTB_MAGIC 0xd00dfeed
+
+/* ------------------------------------------------------------ */
+/* 32-bit zImage Support */
+/* ------------------------------------------------------------ */
+
+#define ZIMAGE32_MAGIC_OFFSET 0x24
+#define ZIMAGE32_START_OFFSET 0x28
+#define ZIMAGE32_END_OFFSET 0x2c
+
+#define ZIMAGE32_MAGIC 0x016f2818
+
+static int xc_dom_probe_zimage32_kernel(struct xc_dom_image *dom)
+{
+ uint32_t *zimage;
+
+ if ( dom->kernel_blob == NULL )
+ {
+ xc_dom_panic(dom->xch, XC_INTERNAL_ERROR,
+ "%s: no kernel image loaded", __FUNCTION__);
+ return -EINVAL;
+ }
+
+ if ( dom->kernel_size < 0x30 /*sizeof(struct setup_header)*/ )
+ {
+ xc_dom_printf(dom->xch, "%s: kernel image too small", __FUNCTION__);
+ return -EINVAL;
+ }
+
+ zimage = (uint32_t *)dom->kernel_blob;
+ if ( zimage[ZIMAGE32_MAGIC_OFFSET/4] != ZIMAGE32_MAGIC )
+ {
+ xc_dom_printf(dom->xch, "%s: kernel is not an arm32 zImage",
__FUNCTION__);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int xc_dom_parse_zimage32_kernel(struct xc_dom_image *dom)
+{
+ uint32_t *zimage;
+ uint32_t start, entry_addr;
+ uint64_t v_start, v_end;
+ uint64_t rambase = dom->rambase_pfn << XC_PAGE_SHIFT;
+
+ DOMPRINTF_CALLED(dom->xch);
+
+ zimage = (uint32_t *)dom->kernel_blob;
+
+ /* Do not load kernel at the very first RAM address */
+ v_start = rambase + 0x8000;
+
+ if ( dom->kernel_size > UINT64_MAX - v_start )
+ {
+ DOMPRINTF("%s: kernel is too large\n", __FUNCTION__);
+ return -EINVAL;
+ }
+
+ v_end = v_start + dom->kernel_size;
+
+ /*
+ * If start is invalid then the guest will start at some invalid
+ * address and crash, but this happens in guest context so doesn't
+ * concern us here.
+ */
+ start = zimage[ZIMAGE32_START_OFFSET/4];
+
+ if (start == 0)
+ entry_addr = v_start;
+ else
+ entry_addr = start;
+
+ /* find kernel segment */
+ dom->kernel_seg.vstart = v_start;
+ dom->kernel_seg.vend = v_end;
+
+ dom->parms.virt_entry = entry_addr;
+ dom->parms.virt_base = rambase;
+
+ dom->guest_type = "xen-3.0-armv7l";
+ DOMPRINTF("%s: %s: 0x%" PRIx64 " -> 0x%" PRIx64 "",
+ __FUNCTION__, dom->guest_type,
+ dom->kernel_seg.vstart, dom->kernel_seg.vend);
+ return 0;
+}
+
+/* ------------------------------------------------------------ */
+/* 64-bit zImage Support */
+/* ------------------------------------------------------------ */
+
+#define ZIMAGE64_MAGIC_V0 0x14000008
+#define ZIMAGE64_MAGIC_V1 0x644d5241 /* "ARM\x64" */
+
+/* linux/Documentation/arm64/booting.txt */
+struct zimage64_hdr {
+ uint32_t magic0;
+ uint32_t res0;
+ uint64_t text_offset; /* Image load offset */
+ uint64_t res1;
+ uint64_t res2;
+ /* zImage V1 only from here */
+ uint64_t res3;
+ uint64_t res4;
+ uint64_t res5;
+ uint32_t magic1;
+ uint32_t res6;
+};
+static int xc_dom_probe_zimage64_kernel(struct xc_dom_image *dom)
+{
+ struct zimage64_hdr *zimage;
+
+ if ( dom->kernel_blob == NULL )
+ {
+ xc_dom_panic(dom->xch, XC_INTERNAL_ERROR,
+ "%s: no kernel image loaded", __FUNCTION__);
+ return -EINVAL;
+ }
+
+ if ( dom->kernel_size < sizeof(*zimage) )
+ {
+ xc_dom_printf(dom->xch, "%s: kernel image too small", __FUNCTION__);
+ return -EINVAL;
+ }
+
+ zimage = dom->kernel_blob;
+ if ( zimage->magic0 != ZIMAGE64_MAGIC_V0 &&
+ zimage->magic1 != ZIMAGE64_MAGIC_V1 )
+ {
+ xc_dom_printf(dom->xch, "%s: kernel is not an arm64 Image",
__FUNCTION__);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int xc_dom_parse_zimage64_kernel(struct xc_dom_image *dom)
+{
+ struct zimage64_hdr *zimage;
+ uint64_t v_start, v_end;
+ uint64_t rambase = dom->rambase_pfn << XC_PAGE_SHIFT;
+
+ DOMPRINTF_CALLED(dom->xch);
+
+ zimage = dom->kernel_blob;
+
+ if ( zimage->text_offset > UINT64_MAX - rambase )
+ {
+ DOMPRINTF("%s: kernel text offset is too large\n", __FUNCTION__);
+ return -EINVAL;
+ }
+
+ v_start = rambase + zimage->text_offset;
+
+ if ( dom->kernel_size > UINT64_MAX - v_start )
+ {
+ DOMPRINTF("%s: kernel is too large\n", __FUNCTION__);
+ return -EINVAL;
+ }
+
+ v_end = v_start + dom->kernel_size;
+
+ dom->kernel_seg.vstart = v_start;
+ dom->kernel_seg.vend = v_end;
+
+ /* Call the kernel at offset 0 */
+ dom->parms.virt_entry = v_start;
+ dom->parms.virt_base = rambase;
+
+ dom->guest_type = "xen-3.0-aarch64";
+ DOMPRINTF("%s: %s: 0x%" PRIx64 " -> 0x%" PRIx64 "",
+ __FUNCTION__, dom->guest_type,
+ dom->kernel_seg.vstart, dom->kernel_seg.vend);
+
+ return 0;
+}
+
+/* ------------------------------------------------------------ */
+/* Common zImage Support */
+/* ------------------------------------------------------------ */
+
+static int xc_dom_load_zimage_kernel(struct xc_dom_image *dom)
+{
+ void *dst;
+
+ DOMPRINTF_CALLED(dom->xch);
+
+ dst = xc_dom_seg_to_ptr(dom, &dom->kernel_seg);
+ if ( dst == NULL )
+ {
+ DOMPRINTF("%s: xc_dom_seg_to_ptr(dom, &dom->kernel_seg) => NULL",
+ __func__);
+ return -1;
+ }
+
+ DOMPRINTF("%s: kernel seg %#"PRIx64"-%#"PRIx64,
+ __func__, dom->kernel_seg.vstart, dom->kernel_seg.vend);
+ DOMPRINTF("%s: copy %zd bytes from blob %p to dst %p",
+ __func__, dom->kernel_size, dom->kernel_blob, dst);
+
+ memcpy(dst, dom->kernel_blob, dom->kernel_size);
+
+ return 0;
+}
+
+static struct xc_dom_loader zimage32_loader = {
+ .name = "Linux zImage (ARM32)",
+ .probe = xc_dom_probe_zimage32_kernel,
+ .parser = xc_dom_parse_zimage32_kernel,
+ .loader = xc_dom_load_zimage_kernel,
+};
+
+static struct xc_dom_loader zimage64_loader = {
+ .name = "Linux zImage (ARM64)",
+ .probe = xc_dom_probe_zimage64_kernel,
+ .parser = xc_dom_parse_zimage64_kernel,
+ .loader = xc_dom_load_zimage_kernel,
+};
+
+static void __init register_loader(void)
+{
+ xc_dom_register_loader(&zimage32_loader);
+ xc_dom_register_loader(&zimage64_loader);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libs/guest/xg_dom_binloader.c
b/tools/libs/guest/xg_dom_binloader.c
new file mode 100644
index 0000000000..870a921427
--- /dev/null
+++ b/tools/libs/guest/xg_dom_binloader.c
@@ -0,0 +1,329 @@
+/*
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Some of the field descriptions were copied from "The Multiboot
+ * Specification", Copyright 1995, 96 Bryan Ford <baford@xxxxxxxxxxx>,
+ * Erich Stefan Boleyn <erich@xxxxxxxx> Copyright 1999, 2000, 2001, 2002
+ * Free Software Foundation, Inc.
+ */
+
+/******************************************************************************
+ *
+ * Loads simple binary images. It's like a .COM file in MS-DOS. No headers are
+ * present. The only requirement is that it must have a xen_bin_image table
+ * somewhere in the first 8192 bytes, starting on a 32-bit aligned address.
+ * Those familiar with the multiboot specification should recognize this, it's
+ * (almost) the same as the multiboot header.
+ * The layout of the xen_bin_image table is:
+ *
+ * Offset Type Name Note
+ * 0 uint32_t magic required
+ * 4 uint32_t flags required
+ * 8 uint32_t checksum required
+ * 12 uint32_t header_addr required
+ * 16 uint32_t load_addr required
+ * 20 uint32_t load_end_addr required
+ * 24 uint32_t bss_end_addr required
+ * 28 uint32_t entry_addr required
+ *
+ * - magic
+ * Magic number identifying the table. For images to be loaded by Xen 3, the
+ * magic value is 0x336ec578 ("xEn3" with the 0x80 bit of the "E" set).
+ * - flags
+ * bit 0: indicates whether the image needs to be loaded on a page boundary
+ * bit 1: reserved, must be 0 (the multiboot spec uses this bit to indicate
+ * that memory info should be passed to the image)
+ * bit 2: reserved, must be 0 (the multiboot spec uses this bit to indicate
+ * that the bootloader should pass video mode info to the image)
+ * bit 16: reserved, must be 1 (the multiboot spec uses this bit to indicate
+ * that the values in the fields header_addr - entry_addr are
+ * valid)
+ * All other bits should be set to 0.
+ * - checksum
+ * When added to "magic" and "flags", the resulting value should be 0.
+ * - header_addr
+ * Contains the virtual address corresponding to the beginning of the
+ * table - the memory location at which the magic value is supposed to be
+ * loaded. This field serves to synchronize the mapping between OS image
+ * offsets and virtual memory addresses.
+ * - load_addr
+ * Contains the virtual address of the beginning of the text segment. The
+ * offset in the OS image file at which to start loading is defined by the
+ * offset at which the table was found, minus (header addr - load addr).
+ * load addr must be less than or equal to header addr.
+ * - load_end_addr
+ * Contains the virtual address of the end of the data segment.
+ * (load_end_addr - load_addr) specifies how much data to load. This implies
+ * that the text and data segments must be consecutive in the OS image. If
+ * this field is zero, the domain builder assumes that the text and data
+ * segments occupy the whole OS image file.
+ * - bss_end_addr
+ * Contains the virtual address of the end of the bss segment. The domain
+ * builder initializes this area to zero, and reserves the memory it occupies
+ * to avoid placing boot modules and other data relevant to the loaded image
+ * in that area. If this field is zero, the domain builder assumes that no
bss
+ * segment is present.
+ * - entry_addr
+ * The virtual address at which to start execution of the loaded image.
+ *
+ */
+
+#include <stdlib.h>
+#include <inttypes.h>
+
+#include "xg_private.h"
+#include "xenctrl_dom.h"
+
+#define round_pgup(_p) (((_p)+(PAGE_SIZE_X86-1))&PAGE_MASK_X86)
+#define round_pgdown(_p) ((_p)&PAGE_MASK_X86)
+
+struct xen_bin_image_table
+{
+ uint32_t magic;
+ uint32_t flags;
+ uint32_t checksum;
+ uint32_t header_addr;
+ uint32_t load_addr;
+ uint32_t load_end_addr;
+ uint32_t bss_end_addr;
+ uint32_t entry_addr;
+};
+
+#define XEN_MULTIBOOT_MAGIC3 0x336ec578
+
+#define XEN_MULTIBOOT_FLAG_ALIGN4K 0x00000001
+#define XEN_MULTIBOOT_FLAG_NEEDMEMINFO 0x00000002
+#define XEN_MULTIBOOT_FLAG_NEEDVIDINFO 0x00000004
+#define XEN_MULTIBOOT_FLAG_ADDRSVALID 0x00010000
+#define XEN_MULTIBOOT_FLAG_PAE_SHIFT 14
+#define XEN_MULTIBOOT_FLAG_PAE_MASK (3 << XEN_MULTIBOOT_FLAG_PAE_SHIFT)
+
+/* Flags we test for */
+#define FLAGS_MASK ((~ 0) & (~ XEN_MULTIBOOT_FLAG_ALIGN4K) & \
+ (~ XEN_MULTIBOOT_FLAG_PAE_MASK))
+#define FLAGS_REQUIRED XEN_MULTIBOOT_FLAG_ADDRSVALID
+
+/* --------------------------------------------------------------------- */
+
+static struct xen_bin_image_table *find_table(struct xc_dom_image *dom)
+{
+ struct xen_bin_image_table *table;
+ uint32_t *probe_ptr;
+ uint32_t *probe_end;
+
+ if ( dom->kernel_size < sizeof(*table) )
+ return NULL;
+ probe_ptr = dom->kernel_blob;
+ if ( dom->kernel_size > (8192 + sizeof(*table)) )
+ probe_end = dom->kernel_blob + 8192;
+ else
+ probe_end = dom->kernel_blob + dom->kernel_size - sizeof(*table);
+
+ for ( table = NULL; probe_ptr < probe_end; probe_ptr++ )
+ {
+ if ( *probe_ptr == XEN_MULTIBOOT_MAGIC3 )
+ {
+ table = (struct xen_bin_image_table *) probe_ptr;
+ /* Checksum correct? */
+ if ( (table->magic + table->flags + table->checksum) == 0 )
+ return table;
+ }
+ }
+ return NULL;
+}
+
+static int xc_dom_probe_bin_kernel(struct xc_dom_image *dom)
+{
+ return find_table(dom) ? 0 : -EINVAL;
+}
+
+static int xc_dom_parse_bin_kernel(struct xc_dom_image *dom)
+{
+ struct xen_bin_image_table *image_info;
+ char *image = dom->kernel_blob;
+ size_t image_size = dom->kernel_size;
+ uint32_t start_addr;
+ uint32_t load_end_addr;
+ uint32_t bss_end_addr;
+ uint32_t pae_flags;
+
+ image_info = find_table(dom);
+ if ( !image_info )
+ return -EINVAL;
+
+ DOMPRINTF("%s: multiboot header fields", __FUNCTION__);
+ DOMPRINTF(" flags: 0x%" PRIx32 "", image_info->flags);
+ DOMPRINTF(" header_addr: 0x%" PRIx32 "", image_info->header_addr);
+ DOMPRINTF(" load_addr: 0x%" PRIx32 "", image_info->load_addr);
+ DOMPRINTF(" load_end_addr: 0x%" PRIx32 "", image_info->load_end_addr);
+ DOMPRINTF(" bss_end_addr: 0x%" PRIx32 "", image_info->bss_end_addr);
+ DOMPRINTF(" entry_addr: 0x%" PRIx32 "", image_info->entry_addr);
+
+ /* Check the flags */
+ if ( (image_info->flags & FLAGS_MASK) != FLAGS_REQUIRED )
+ {
+ xc_dom_panic(dom->xch, XC_INVALID_KERNEL,
+ "%s: xen_bin_image_table flags required "
+ "0x%08" PRIx32 " found 0x%08" PRIx32 "",
+ __FUNCTION__, FLAGS_REQUIRED, image_info->flags &
FLAGS_MASK);
+ return -EINVAL;
+ }
+
+ /* Sanity check on the addresses */
+ if ( (image_info->header_addr < image_info->load_addr) ||
+ ((char *) image_info - image) <
+ (image_info->header_addr - image_info->load_addr) )
+ {
+ xc_dom_panic(dom->xch, XC_INVALID_KERNEL, "%s: Invalid header_addr.",
+ __FUNCTION__);
+ return -EINVAL;
+ }
+
+ start_addr = image_info->header_addr - ((char *)image_info - image);
+ load_end_addr = image_info->load_end_addr ?: start_addr + image_size;
+ bss_end_addr = image_info->bss_end_addr ?: load_end_addr;
+
+ DOMPRINTF("%s: calculated addresses", __FUNCTION__);
+ DOMPRINTF(" start_addr: 0x%" PRIx32 "", start_addr);
+ DOMPRINTF(" load_end_addr: 0x%" PRIx32 "", load_end_addr);
+ DOMPRINTF(" bss_end_addr: 0x%" PRIx32 "", bss_end_addr);
+
+ if ( (start_addr + image_size) < load_end_addr )
+ {
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |