[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [xen staging] 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 |