summary refs log tree commit diff
diff options
context:
space:
mode:
authorGraham Christensen <graham@grahamc.com>2017-03-07 18:52:40 -0500
committerGitHub <noreply@github.com>2017-03-07 18:52:40 -0500
commit9e6ae2f60a109c6e5380c0fb3775e783a1fc8f00 (patch)
tree180359b9070bbce4be8e1dc49ef923804f166e97
parente206d5ab63b64b377c22488ac0b33481bef9bf21 (diff)
parent442b8d49d0e973d2f78bd424efab55d33f6ae98c (diff)
downloadnixlib-9e6ae2f60a109c6e5380c0fb3775e783a1fc8f00.tar
nixlib-9e6ae2f60a109c6e5380c0fb3775e783a1fc8f00.tar.gz
nixlib-9e6ae2f60a109c6e5380c0fb3775e783a1fc8f00.tar.bz2
nixlib-9e6ae2f60a109c6e5380c0fb3775e783a1fc8f00.tar.lz
nixlib-9e6ae2f60a109c6e5380c0fb3775e783a1fc8f00.tar.xz
nixlib-9e6ae2f60a109c6e5380c0fb3775e783a1fc8f00.tar.zst
nixlib-9e6ae2f60a109c6e5380c0fb3775e783a1fc8f00.zip
Merge pull request #23441 from oxij/pkg/pretty-xen
xen: modular expression
-rw-r--r--nixos/modules/virtualisation/xen-dom0.nix66
-rw-r--r--pkgs/applications/virtualization/qemu/default.nix15
-rw-r--r--pkgs/applications/virtualization/xen/0000-fix-install-python.patch16
-rw-r--r--pkgs/applications/virtualization/xen/0000-fix-ipxe-src.patch27
-rw-r--r--pkgs/applications/virtualization/xen/4.5.nix375
-rw-r--r--pkgs/applications/virtualization/xen/generic.nix321
-rw-r--r--pkgs/applications/virtualization/xen/packages.nix64
-rw-r--r--pkgs/top-level/all-packages.nix14
8 files changed, 583 insertions, 315 deletions
diff --git a/nixos/modules/virtualisation/xen-dom0.nix b/nixos/modules/virtualisation/xen-dom0.nix
index 67eef0ec1e4c..a80b2e1f3b04 100644
--- a/nixos/modules/virtualisation/xen-dom0.nix
+++ b/nixos/modules/virtualisation/xen-dom0.nix
@@ -27,6 +27,36 @@ in
           '';
       };
 
+    virtualisation.xen.package = mkOption {
+      type = types.package;
+      default = pkgs.xen;
+      defaultText = "pkgs.xen";
+      example = literalExample "pkgs.xen-light";
+      description = ''
+        The package used for Xen binary.
+      '';
+    };
+
+    virtualisation.xen.qemu = mkOption {
+      type = types.path;
+      default = "${pkgs.xen}/lib/xen/bin/qemu-system-i386";
+      defaultText = "''${pkgs.xen}/lib/xen/bin/qemu-system-i386";
+      example = literalExample "''${pkgs.qemu_xen-light}/bin/qemu-system-i386";
+      description = ''
+        The qemu binary to use for Dom-0 backend.
+      '';
+    };
+
+    virtualisation.xen.qemu-package = mkOption {
+      type = types.package;
+      default = pkgs.xen;
+      defaultText = "pkgs.xen";
+      example = literalExample "pkgs.qemu_xen-light";
+      description = ''
+        The package with qemu binaries for xendomains.
+      '';
+    };
+
     virtualisation.xen.bootParams =
       mkOption {
         default = "";
@@ -106,9 +136,9 @@ in
       message = "Xen currently does not support EFI boot";
     } ];
 
-    virtualisation.xen.stored = mkDefault "${pkgs.xen}/bin/oxenstored";
+    virtualisation.xen.stored = mkDefault "${cfg.package}/bin/oxenstored";
 
-    environment.systemPackages = [ pkgs.xen ];
+    environment.systemPackages = [ cfg.package ];
 
     # Make sure Domain 0 gets the required configuration
     #boot.kernelPackages = pkgs.boot.kernelPackages.override { features={xen_dom0=true;}; };
@@ -144,7 +174,7 @@ in
 
     system.extraSystemBuilderCmds =
       ''
-        ln -s ${pkgs.xen}/boot/xen.gz $out/xen.gz
+        ln -s ${cfg.package}/boot/xen.gz $out/xen.gz
         echo "${toString cfg.bootParams}" > $out/xen-params
       '';
 
@@ -180,19 +210,19 @@ in
 
 
     environment.etc =
-      [ { source = "${pkgs.xen}/etc/xen/xl.conf";
+      [ { source = "${cfg.package}/etc/xen/xl.conf";
           target = "xen/xl.conf";
         }
-        { source = "${pkgs.xen}/etc/xen/scripts";
+        { source = "${cfg.package}/etc/xen/scripts";
           target = "xen/scripts";
         }
-        { source = "${pkgs.xen}/etc/default/xendomains";
+        { source = "${cfg.package}/etc/default/xendomains";
           target = "default/xendomains";
         }
       ];
 
     # Xen provides udev rules.
-    services.udev.packages = [ pkgs.xen ];
+    services.udev.packages = [ cfg.package ];
 
     services.udev.path = [ pkgs.bridge-utils pkgs.iproute ];
 
@@ -217,7 +247,7 @@ in
         time=0
         timeout=30
         # Wait for xenstored to actually come up, timing out after 30 seconds
-        while [ $time -lt $timeout ] && ! `${pkgs.xen}/bin/xenstore-read -s / >/dev/null 2>&1` ; do
+        while [ $time -lt $timeout ] && ! `${cfg.package}/bin/xenstore-read -s / >/dev/null 2>&1` ; do
             time=$(($time+1))
             sleep 1
         done
@@ -228,8 +258,8 @@ in
             exit 1
         fi
 
-        ${pkgs.xen}/bin/xenstore-write "/local/domain/0/name" "Domain-0"
-        ${pkgs.xen}/bin/xenstore-write "/local/domain/0/domid" 0
+        ${cfg.package}/bin/xenstore-write "/local/domain/0/name" "Domain-0"
+        ${cfg.package}/bin/xenstore-write "/local/domain/0/domid" 0
         '';
     };
 
@@ -256,7 +286,7 @@ in
         '';
       serviceConfig = {
         ExecStart = ''
-          ${pkgs.xen}/bin/xenconsoled${optionalString cfg.trace " --log=all --log-dir=/var/log/xen"}
+          ${cfg.package}/bin/xenconsoled${optionalString cfg.trace " --log=all --log-dir=/var/log/xen"}
           '';
       };
     };
@@ -267,8 +297,8 @@ in
       wantedBy = [ "multi-user.target" ];
       after = [ "xen-console.service" ];
       serviceConfig.ExecStart = ''
-        ${pkgs.xen}/lib/xen/bin/qemu-system-i386 -xen-domid 0 -xen-attach -name dom0 -nographic -M xenpv \
-           -monitor /dev/null -serial /dev/null -parallel /dev/null
+        ${cfg.qemu} -xen-attach -xen-domid 0 -name dom0 -M xenpv \
+           -nographic -monitor /dev/null -serial /dev/null -parallel /dev/null
         '';
     };
 
@@ -277,7 +307,7 @@ in
       description = "Xen Watchdog Daemon";
       wantedBy = [ "multi-user.target" ];
       after = [ "xen-qemu.service" ];
-      serviceConfig.ExecStart = "${pkgs.xen}/bin/xenwatchdogd 30 15";
+      serviceConfig.ExecStart = "${cfg.package}/bin/xenwatchdogd 30 15";
       serviceConfig.Type = "forking";
       serviceConfig.RestartSec = "1";
       serviceConfig.Restart = "on-failure";
@@ -366,11 +396,11 @@ in
       before = [ "dhcpd.service" ];
       restartIfChanged = false;
       serviceConfig.RemainAfterExit = "yes";
-      path = [ pkgs.xen ];
-      environment.XENDOM_CONFIG = "${pkgs.xen}/etc/sysconfig/xendomains";
+      path = [ cfg.package cfg.qemu-package ];
+      environment.XENDOM_CONFIG = "${cfg.package}/etc/sysconfig/xendomains";
       preStart = "mkdir -p /var/lock/subsys -m 755";
-      serviceConfig.ExecStart = "${pkgs.xen}/etc/init.d/xendomains start";
-      serviceConfig.ExecStop = "${pkgs.xen}/etc/init.d/xendomains stop";
+      serviceConfig.ExecStart = "${cfg.package}/etc/init.d/xendomains start";
+      serviceConfig.ExecStop = "${cfg.package}/etc/init.d/xendomains stop";
     };
 
   };
diff --git a/pkgs/applications/virtualization/qemu/default.nix b/pkgs/applications/virtualization/qemu/default.nix
index b201e2299310..8d462395ce07 100644
--- a/pkgs/applications/virtualization/qemu/default.nix
+++ b/pkgs/applications/virtualization/qemu/default.nix
@@ -9,7 +9,9 @@
 , pulseSupport ? !stdenv.isDarwin, libpulseaudio
 , sdlSupport ? !stdenv.isDarwin, SDL
 , vncSupport ? true, libjpeg, libpng
-, spiceSupport ? !stdenv.isDarwin, spice, spice_protocol, usbredir
+, spiceSupport ? !stdenv.isDarwin, spice, spice_protocol
+, usbredirSupport ? spiceSupport, usbredir
+, xenSupport ? false, xen
 , x86Only ? false
 , nixosTestRunner ? false
 }:
@@ -24,6 +26,7 @@ in
 
 stdenv.mkDerivation rec {
   name = "qemu-"
+    + stdenv.lib.optionalString xenSupport "xen-"
     + stdenv.lib.optionalString x86Only "x86-only-"
     + stdenv.lib.optionalString nixosTestRunner "for-vm-tests-"
     + version;
@@ -44,8 +47,10 @@ stdenv.mkDerivation rec {
     ++ optionals pulseSupport [ libpulseaudio ]
     ++ optionals sdlSupport [ SDL ]
     ++ optionals vncSupport [ libjpeg libpng ]
-    ++ optionals spiceSupport [ spice_protocol spice usbredir ]
-    ++ optionals stdenv.isLinux [ alsaLib libaio libcap_ng libcap attr ];
+    ++ optionals spiceSupport [ spice_protocol spice ]
+    ++ optionals usbredirSupport [ usbredir ]
+    ++ optionals stdenv.isLinux [ alsaLib libaio libcap_ng libcap attr ]
+    ++ optionals xenSupport [ xen ];
 
   enableParallelBuilding = true;
 
@@ -95,9 +100,11 @@ stdenv.mkDerivation rec {
     ++ optional numaSupport "--enable-numa"
     ++ optional seccompSupport "--enable-seccomp"
     ++ optional spiceSupport "--enable-spice"
+    ++ optional usbredirSupport "--enable-usb-redir"
     ++ optional x86Only "--target-list=i386-softmmu,x86_64-softmmu"
     ++ optional stdenv.isDarwin "--enable-cocoa"
-    ++ optional stdenv.isLinux "--enable-linux-aio";
+    ++ optional stdenv.isLinux "--enable-linux-aio"
+    ++ optional xenSupport "--enable-xen";
 
   postFixup =
     ''
diff --git a/pkgs/applications/virtualization/xen/0000-fix-install-python.patch b/pkgs/applications/virtualization/xen/0000-fix-install-python.patch
new file mode 100644
index 000000000000..53821c0d9c51
--- /dev/null
+++ b/pkgs/applications/virtualization/xen/0000-fix-install-python.patch
@@ -0,0 +1,16 @@
+tools/python/install-wrap script brakes shebangs patching, disable
+
+diff --git a/tools/Rules.mk b/tools/Rules.mk
+index 87a56dc..a7da869 100644
+--- a/tools/Rules.mk
++++ b/tools/Rules.mk
+@@ -90,8 +90,7 @@ CFLAGS += $(CFLAGS-y)
+ 
+ CFLAGS += $(EXTRA_CFLAGS_XEN_TOOLS)
+ 
+-INSTALL_PYTHON_PROG = \
+-	$(XEN_ROOT)/tools/python/install-wrap "$(PYTHON_PATH)" $(INSTALL_PROG)
++INSTALL_PYTHON_PROG = $(INSTALL_PROG)
+ 
+ %.opic: %.c
+ 	$(CC) $(CPPFLAGS) -DPIC $(CFLAGS) $(CFLAGS_$*.opic) -fPIC -c -o $@ $< $(APPEND_CFLAGS)
diff --git a/pkgs/applications/virtualization/xen/0000-fix-ipxe-src.patch b/pkgs/applications/virtualization/xen/0000-fix-ipxe-src.patch
new file mode 100644
index 000000000000..072338b87aba
--- /dev/null
+++ b/pkgs/applications/virtualization/xen/0000-fix-ipxe-src.patch
@@ -0,0 +1,27 @@
+hack to make etherboot use prefetched ipxe
+
+diff --git a/tools/firmware/etherboot/Makefile b/tools/firmware/etherboot/Makefile
+index a0578d2..64428a0 100644
+--- a/tools/firmware/etherboot/Makefile
++++ b/tools/firmware/etherboot/Makefile
+@@ -16,6 +16,7 @@ IPXE_TARBALL_URL ?= $(XEN_EXTFILES_URL)/ipxe-git-$(IPXE_GIT_TAG).tar.gz
+ 
+ D=ipxe
+ T=ipxe.tar.gz
++G=ipxe.git
+ 
+ ROMS = $(addprefix $D/src/bin/, $(addsuffix .rom, $(ETHERBOOT_NICS)))
+ 
+@@ -36,9 +37,9 @@ $T:
+ 	fi
+ 	mv _$T $T
+ 
+-$D/src/arch/i386/Makefile: $T Config
+-	rm -rf $D
+-	gzip -dc $T | tar xf -
++$D/src/arch/i386/Makefile: $G Config
++	mkdir $D
++	cp -a $G/* $D
+ 	for i in $$(cat patches/series) ; do                 \
+ 	    patch -d $D -p1 --quiet <patches/$$i || exit 1 ; \
+ 	done
diff --git a/pkgs/applications/virtualization/xen/4.5.nix b/pkgs/applications/virtualization/xen/4.5.nix
index bc8d89af5b2a..754f800afada 100644
--- a/pkgs/applications/virtualization/xen/4.5.nix
+++ b/pkgs/applications/virtualization/xen/4.5.nix
@@ -1,152 +1,237 @@
-{ callPackage, fetchurl, fetchpatch, fetchgit, ... } @ args:
+{ stdenv, callPackage, fetchurl, fetchpatch, fetchgit
+, withInternalQemu ? true
+, withInternalTraditionalQemu ? true
+, withInternalSeabios ? true
+, withSeabios ? !withInternalSeabios, seabios ? null
+, withInternalOVMF ? false # FIXME: tricky to build
+, withOVMF ? false, OVMF
+, withLibHVM ? true
+
+# qemu
+, udev, pciutils, xorg, SDL, pixman, acl, glusterfs, spice_protocol, usbredir
+, alsaLib
+, ... } @ args:
+
+assert withInternalSeabios -> !withSeabios;
+assert withInternalOVMF -> !withOVMF;
+
+with stdenv.lib;
+
+# Patching XEN? Check the XSAs at
+# https://xenbits.xen.org/xsa/
+# and try applying all the ones we don't have yet.
 
 let
-  # Xen 4.5.5
-  #
-  # Patching XEN? Check the XSAs and try applying all the ones we
-  # don't have yet.
-  #
-  # XSAs at: https://xenbits.xen.org/xsa/
-  xenConfig = rec {
-    version = "4.5.5";
-
-    xsaPatch = { name , sha256 }: (fetchpatch {
-      url = "https://xenbits.xen.org/xsa/xsa${name}.patch";
-      inherit sha256;
-    });
-
-    name = "xen-${version}";
-
-    src = fetchurl {
-      url = "http://bits.xensource.com/oss-xen/release/${version}/${name}.tar.gz";
-      sha256 = "1y74ms4yc3znf8jc3fgyq94va2y0pf7jh8m9pfqnpgklywqnw8g2";
-    };
+  xsaPatch = { name , sha256 }: (fetchpatch {
+    url = "https://xenbits.xen.org/xsa/xsa${name}.patch";
+    inherit sha256;
+  });
 
-    # Sources needed to build the xen tools and tools/firmware.
-    firmwareGits =
-      [
-        { git = { name = "seabios";
-                  url = https://xenbits.xen.org/git-http/seabios.git;
-                  rev = "rel-1.7.5";
-                  sha256 = "0jk54ybhmw97pzyhpm6jr2x99f702kbn0ipxv5qxcbynflgdazyb";
-                };
-          patches = [ ./0000-qemu-seabios-enable-ATA_DMA.patch ];
-        }
-      ];
+  qemuDeps = [
+    udev pciutils xorg.libX11 SDL pixman acl glusterfs spice_protocol usbredir
+    alsaLib
+  ];
+in
 
-    toolsGits =
-      [
-        { git = { name = "qemu-xen";
-                  url = https://xenbits.xen.org/git-http/qemu-xen.git;
-                  rev = "refs/tags/qemu-xen-${version}";
-                  sha256 = "014s755slmsc7xzy7qhk9i3kbjr2grxb5yznjp71dl6xxfvnday2";
-                };
-          patches = [
-            (xsaPatch {
-              name = "197-4.5-qemuu";
-              sha256 = "09gp980qdlfpfmxy0nk7ncyaa024jnrpzx9gpq2kah21xygy5myx";
-            })
-            (xsaPatch {
-              name = "208-qemuu-4.7";
-              sha256 = "0z9b1whr8rp2riwq7wndzcnd7vw1ckwx0vbk098k2pcflrzppgrb";
-            })
-            (xsaPatch {
-              name = "209-qemuu";
-              sha256 = "05df4165by6pzxrnizkw86n2f77k9i1g4fqqpws81ycb9ng4jzin";
-            })
-          ];
-        }
-        { git = { name = "qemu-xen-traditional";
-                  url = https://xenbits.xen.org/git-http/qemu-xen-traditional.git;
-                  # rev = "28c21388c2a32259cff37fc578684f994dca8c9f";
-                  rev = "refs/tags/xen-${version}";
-                  sha256 = "0n0ycxlf1wgdjkdl8l2w1i0zzssk55dfv67x8i6b2ima01r0k93r";
-                };
-          patches = [
-            (xsaPatch {
-              name = "197-4.5-qemut";
-              sha256 = "17l7npw00gyhqzzaqamwm9cawfvzm90zh6jjyy95dmqbh7smvy79";
-            })
-            (xsaPatch {
-              name = "199-trad";
-              sha256 = "0dfw6ciycw9a9s97sbnilnzhipnzmdm9f7xcfngdjfic8cqdcv42";
-            })
-            (xsaPatch {
-              name = "208-qemut";
-              sha256 = "0960vhchixp60j9h2lawgbgzf6mpcdk440kblk25a37bd6172l54";
-            })
-            (xsaPatch {
-              name = "209-qemut";
-              sha256 = "1hq8ghfzw6c47pb5vf9ngxwgs8slhbbw6cq7gk0nam44rwvz743r";
-            })
-          ];
-        }
-        { git = { name = "xen-libhvm";
-                  url = https://github.com/ts468/xen-libhvm;
-                  rev = "442dcc4f6f4e374a51e4613532468bd6b48bdf63";
-                  sha256 = "9ba97c39a00a54c154785716aa06691d312c99be498ebbc00dc3769968178ba8";
-                };
-          description = ''
-            Helper library for reading ACPI and SMBIOS firmware values
-            from the host system for use with the HVM guest firmware
-            pass-through feature in Xen.
-            '';
-          #license = licenses.bsd2;
-        }
-      ];
+callPackage (import ./generic.nix (rec {
+  version = "4.5.5";
 
-      xenPatches = [ ./0001-libxl-Spice-image-compression-setting-support-for-up.patch
-                     ./0002-libxl-Spice-streaming-video-setting-support-for-upst.patch
-                     ./0003-Add-qxl-vga-interface-support-for-upstream-qem.patch
-                     (xsaPatch {
-                       name = "190-4.5";
-                       sha256 = "0f8pw38kkxky89ny3ic5h26v9zsjj9id89lygx896zc3w1klafqm";
-                     })
-                     (xsaPatch {
-                       name = "191-4.6";
-                       sha256 = "1wl1ndli8rflmc44pkp8cw4642gi8z7j7gipac8mmlavmn3wdqhg";
-                     })
-                     (xsaPatch {
-                       name = "192-4.5";
-                       sha256 = "0m8cv0xqvx5pdk7fcmaw2vv43xhl62plyx33xqj48y66x5z9lxpm";
-                     })
-                     (xsaPatch {
-                       name = "193-4.5";
-                       sha256 = "0k9mykhrpm4rbjkhv067f6s05lqmgnldcyb3vi8cl0ndlyh66lvr";
-                     })
-                     (xsaPatch {
-                       name = "195";
-                       sha256 = "0m0g953qnjy2knd9qnkdagpvkkgjbk3ydgajia6kzs499dyqpdl7";
-                     })
-                     (xsaPatch {
-                       name = "196-0001-x86-emul-Correct-the-IDT-entry-calculation-in-inject";
-                       sha256 = "0z53nzrjvc745y26z1qc8jlg3blxp7brawvji1hx3s74n346ssl6";
-                     })
-                     (xsaPatch {
-                       name = "196-0002-x86-svm-Fix-injection-of-software-interrupts";
-                       sha256 = "11cqvr5jn2s92wsshpilx9qnfczrd9hnyb5aim6qwmz3fq3hrrkz";
-                     })
-                     (xsaPatch {
-                       name = "198";
-                       sha256 = "0d1nndn4p520c9xa87ixnyks3mrvzcri7c702d6mm22m8ansx6d9";
-                     })
-                     (xsaPatch {
-                       name = "200-4.6";
-                       sha256 = "0k918ja83470iz5k4vqi15293zjvz2dipdhgc9sy9rrhg4mqncl7";
-                     })
-                     (xsaPatch {
-                       name = "202-4.6";
-                       sha256 = "0nnznkrvfbbc8z64dr9wvbdijd4qbpc0wz2j5vpmx6b32sm7932f";
-                     })
-                     (xsaPatch {
-                       name = "204-4.5";
-                       sha256 = "083z9pbdz3f532fnzg7n2d5wzv6rmqc0f4mvc3mnmkd0rzqw8vcp";
-                     })
-                     (xsaPatch {
-                       name = "207";
-                       sha256 = "0wdlhijmw9mdj6a82pyw1rwwiz605dwzjc392zr3fpb2jklrvibc";
-                     })
-                   ];
+  src = fetchurl {
+    url = "http://bits.xensource.com/oss-xen/release/${version}/xen-${version}.tar.gz";
+    sha256 = "1y74ms4yc3znf8jc3fgyq94va2y0pf7jh8m9pfqnpgklywqnw8g2";
   };
 
-in callPackage ./generic.nix (args // { xenConfig=xenConfig; })
+  # Sources needed to build tools and firmwares.
+  xenfiles = optionalAttrs withInternalQemu {
+    "qemu-xen" = {
+      src = fetchgit {
+        url = https://xenbits.xen.org/git-http/qemu-xen.git;
+        rev = "refs/tags/qemu-xen-${version}";
+        sha256 = "014s755slmsc7xzy7qhk9i3kbjr2grxb5yznjp71dl6xxfvnday2";
+      };
+      buildInputs = qemuDeps;
+      patches = [
+        (xsaPatch {
+          name = "197-4.5-qemuu";
+          sha256 = "09gp980qdlfpfmxy0nk7ncyaa024jnrpzx9gpq2kah21xygy5myx";
+        })
+        (xsaPatch {
+          name = "208-qemuu-4.7";
+          sha256 = "0z9b1whr8rp2riwq7wndzcnd7vw1ckwx0vbk098k2pcflrzppgrb";
+        })
+        (xsaPatch {
+          name = "209-qemuu/0001-display-cirrus-ignore-source-pitch-value-as-needed-i";
+          sha256 = "1xvxzsrsq05fj6szjlpbgg4ia3cw54dn5g7xzq1n1dymbhv606m0";
+        })
+        (xsaPatch {
+          name = "209-qemuu/0002-cirrus-add-blit_is_unsafe-call-to-cirrus_bitblt_cput";
+          sha256 = "0avxqs9922qjfsxxlk7bh10432a526j2yyykhags8dk1bzxkpxwv";
+        })
+      ];
+      meta.description = "Xen's fork of upstream Qemu";
+    };
+  } // optionalAttrs withInternalTraditionalQemu {
+    "qemu-xen-traditional" = {
+      src = fetchgit {
+        url = https://xenbits.xen.org/git-http/qemu-xen-traditional.git;
+        rev = "refs/tags/xen-${version}";
+        sha256 = "0n0ycxlf1wgdjkdl8l2w1i0zzssk55dfv67x8i6b2ima01r0k93r";
+      };
+      buildInputs = qemuDeps;
+      patches = [
+        (xsaPatch {
+          name = "197-4.5-qemut";
+          sha256 = "17l7npw00gyhqzzaqamwm9cawfvzm90zh6jjyy95dmqbh7smvy79";
+        })
+        (xsaPatch {
+          name = "199-trad";
+          sha256 = "0dfw6ciycw9a9s97sbnilnzhipnzmdm9f7xcfngdjfic8cqdcv42";
+        })
+        (xsaPatch {
+          name = "208-qemut";
+          sha256 = "0960vhchixp60j9h2lawgbgzf6mpcdk440kblk25a37bd6172l54";
+        })
+        (xsaPatch {
+          name = "209-qemut";
+          sha256 = "1hq8ghfzw6c47pb5vf9ngxwgs8slhbbw6cq7gk0nam44rwvz743r";
+        })
+      ];
+      postPatch = ''
+        substituteInPlace xen-hooks.mak \
+          --replace /usr/include/pci ${pciutils}/include/pci
+      '';
+      meta.description = "Xen's fork of upstream Qemu that uses old device model";
+    };
+  } // optionalAttrs withInternalSeabios {
+    "firmware/seabios-dir-remote" = {
+      src = fetchgit {
+        url = https://xenbits.xen.org/git-http/seabios.git;
+        rev = "e51488c5f8800a52ac5c8da7a31b85cca5cc95d2";
+        #rev = "rel-1.7.5";
+        sha256 = "0jk54ybhmw97pzyhpm6jr2x99f702kbn0ipxv5qxcbynflgdazyb";
+      };
+      patches = [ ./0000-qemu-seabios-enable-ATA_DMA.patch ];
+      meta.description = "Xen's fork of Seabios";
+    };
+  } // optionalAttrs withInternalOVMF {
+    "firmware/ovmf-dir-remote" = {
+      src = fetchgit {
+        url = https://xenbits.xen.org/git-http/ovmf.git;
+        rev = "cb9a7ebabcd6b8a49dc0854b2f9592d732b5afbd";
+        sha256 = "07zmdj90zjrzip74fvd4ss8n8njk6cim85s58mc6snxmqqv7gmcq";
+      };
+      meta.description = "Xen's fork of OVMF";
+    };
+  } // {
+    # TODO: patch Xen to make this optional?
+    "firmware/etherboot/ipxe.git" = {
+      src = fetchgit {
+        url = https://git.ipxe.org/ipxe.git;
+        rev = "9a93db3f0947484e30e753bbd61a10b17336e20e";
+        sha256 = "1ga3h1b34q0cl9azj7j9nswn7mfcs3cgfjdihrm5zkp2xw2hpvr6";
+      };
+      meta.description = "Xen's fork of iPXE";
+    };
+  } // optionalAttrs withLibHVM {
+    "xen-libhvm-dir-remote" = {
+      src = fetchgit {
+        name = "xen-libhvm";
+        url = https://github.com/ts468/xen-libhvm;
+        rev = "442dcc4f6f4e374a51e4613532468bd6b48bdf63";
+        sha256 = "9ba97c39a00a54c154785716aa06691d312c99be498ebbc00dc3769968178ba8";
+      };
+      buildPhase = ''
+        make
+        cd biospt
+        cc -Wall -g -D_LINUX -Wstrict-prototypes biospt.c -o biospt -I../libhvm -L../libhvm -lxenhvm
+      '';
+      installPhase = ''
+        make install
+        cp biospt/biospt $out/bin/
+      '';
+      meta = {
+        description = ''
+          Helper library for reading ACPI and SMBIOS firmware values
+          from the host system for use with the HVM guest firmware
+          pass-through feature in Xen'';
+        license = licenses.bsd2;
+      };
+    };
+  };
+
+  configureFlags = []
+    ++ optional (!withInternalQemu) "--with-system-qemu" # use qemu from PATH
+    ++ optional (withInternalTraditionalQemu) "--enable-qemu-traditional"
+    ++ optional (!withInternalTraditionalQemu) "--disable-qemu-traditional"
+
+    ++ optional (withSeabios) "--with-system-seabios=${seabios}"
+    ++ optional (!withInternalSeabios && !withSeabios) "--disable-seabios"
+
+    ++ optional (withOVMF) "--with-system-ovmf=${OVMF}"
+    ++ optional (withInternalOVMF) "--enable-ovmf";
+
+  patches =
+    [ ./0001-libxl-Spice-image-compression-setting-support-for-up.patch
+      ./0002-libxl-Spice-streaming-video-setting-support-for-upst.patch
+      ./0003-Add-qxl-vga-interface-support-for-upstream-qem.patch
+      (xsaPatch {
+        name = "190-4.5";
+        sha256 = "0f8pw38kkxky89ny3ic5h26v9zsjj9id89lygx896zc3w1klafqm";
+      })
+      (xsaPatch {
+        name = "191-4.6";
+        sha256 = "1wl1ndli8rflmc44pkp8cw4642gi8z7j7gipac8mmlavmn3wdqhg";
+      })
+      (xsaPatch {
+        name = "192-4.5";
+        sha256 = "0m8cv0xqvx5pdk7fcmaw2vv43xhl62plyx33xqj48y66x5z9lxpm";
+      })
+      (xsaPatch {
+        name = "193-4.5";
+        sha256 = "0k9mykhrpm4rbjkhv067f6s05lqmgnldcyb3vi8cl0ndlyh66lvr";
+      })
+      (xsaPatch {
+        name = "195";
+        sha256 = "0m0g953qnjy2knd9qnkdagpvkkgjbk3ydgajia6kzs499dyqpdl7";
+      })
+      (xsaPatch {
+        name = "196-0001-x86-emul-Correct-the-IDT-entry-calculation-in-inject";
+        sha256 = "0z53nzrjvc745y26z1qc8jlg3blxp7brawvji1hx3s74n346ssl6";
+      })
+      (xsaPatch {
+        name = "196-0002-x86-svm-Fix-injection-of-software-interrupts";
+        sha256 = "11cqvr5jn2s92wsshpilx9qnfczrd9hnyb5aim6qwmz3fq3hrrkz";
+      })
+      (xsaPatch {
+        name = "198";
+        sha256 = "0d1nndn4p520c9xa87ixnyks3mrvzcri7c702d6mm22m8ansx6d9";
+      })
+      (xsaPatch {
+        name = "200-4.6";
+        sha256 = "0k918ja83470iz5k4vqi15293zjvz2dipdhgc9sy9rrhg4mqncl7";
+      })
+      (xsaPatch {
+        name = "202-4.6";
+        sha256 = "0nnznkrvfbbc8z64dr9wvbdijd4qbpc0wz2j5vpmx6b32sm7932f";
+      })
+      (xsaPatch {
+        name = "204-4.5";
+        sha256 = "083z9pbdz3f532fnzg7n2d5wzv6rmqc0f4mvc3mnmkd0rzqw8vcp";
+      })
+      (xsaPatch {
+        name = "207";
+        sha256 = "0wdlhijmw9mdj6a82pyw1rwwiz605dwzjc392zr3fpb2jklrvibc";
+      })
+    ];
+
+  # Fix build on Glibc 2.24.
+  NIX_CFLAGS_COMPILE = "-Wno-error=deprecated-declarations";
+
+  postPatch = ''
+    # Avoid a glibc >= 2.25 deprecation warnings that get fatal via -Werror.
+    sed 1i'#include <sys/sysmacros.h>' \
+      -i tools/blktap2/control/tap-ctl-allocate.c \
+      -i tools/libxl/libxl_device.c
+  '';
+
+})) args
diff --git a/pkgs/applications/virtualization/xen/generic.nix b/pkgs/applications/virtualization/xen/generic.nix
index 9943d70fa8cd..953368b7e3bc 100644
--- a/pkgs/applications/virtualization/xen/generic.nix
+++ b/pkgs/applications/virtualization/xen/generic.nix
@@ -1,188 +1,219 @@
-{ stdenv, fetchurl, which, zlib, pkgconfig, SDL, openssl
-, libuuid, gettext, ncurses, dev86, iasl, pciutils, bzip2
-, lvm2, utillinux, procps, texinfo, perl, python2Packages
-, glib, bridge-utils, xorg, pixman, iproute, udev, bison
-, flex, cmake, ocamlPackages, figlet, libaio, yajl
-, checkpolicy, transfig, glusterfs, acl, fetchgit, xz, spice
-, spice_protocol, usbredir, alsaLib, quilt
+config:
+{ stdenv, cmake, pkgconfig, which
+
+# Xen
+, bison, bzip2, checkpolicy, dev86, figlet, flex, gettext, glib
+, iasl, libaio, libiconv, libuuid, ncurses, openssl, perl
+, python2Packages
+# python2Packages.python
+, xz, yajl, zlib
+
+# Xen Optional
+, ocamlPackages
+
+# Scripts
 , coreutils, gawk, gnused, gnugrep, diffutils, multipath-tools
-, inetutils, iptables, openvswitch, nbd, drbd, xenConfig
-, xenserverPatched ? false, ... }:
+, iproute, inetutils, iptables, bridge-utils, openvswitch, nbd, drbd
+, lvm2, utillinux, procps
+
+# Documentation
+# python2Packages.markdown
+, transfig, ghostscript, texinfo, pandoc
+
+, ...} @ args:
 
 with stdenv.lib;
 
 let
+  #TODO: fix paths instead
+  scriptEnvPath = concatMapStringsSep ":" (x: "${x}/bin") [
+    which perl
+    coreutils gawk gnused gnugrep diffutils utillinux multipath-tools
+    iproute inetutils iptables bridge-utils openvswitch nbd drbd
+  ];
+
+  withXenfiles = f: concatStringsSep "\n" (mapAttrsToList f config.xenfiles);
+
+  withTools = a: f: withXenfiles (name: x: optionalString (hasAttr a x) ''
+    echo "processing ${name}"
+    __do() {
+      cd "tools/${name}"
+      ${f name x}
+    }
+    ( __do )
+  '');
+in
 
-  libDir = if stdenv.is64bit then "lib64" else "lib";
+stdenv.mkDerivation (rec {
+  inherit (config) version;
 
-  # Sources needed to build the tools
-  # These sources are already rather old and probably do not change frequently
-  xenExtfiles = [
-      { url = http://xenbits.xensource.com/xen-extfiles/ipxe-git-9a93db3f0947484e30e753bbd61a10b17336e20e.tar.gz;
-        sha256 = "0p206zaxlhda60ci33h9gipi5gm46fvvsm6k5c0w7b6cjg0yhb33";
-      }
-    ];
+  name = "xen-${version}";
 
-  scriptEnvPath = stdenv.lib.concatStrings (stdenv.lib.intersperse ":" (map (x: "${x}/bin")
-    [ coreutils gawk gnused gnugrep which perl diffutils utillinux multipath-tools
-      iproute inetutils iptables bridge-utils openvswitch nbd drbd ]));
-in
+  dontUseCmakeConfigure = true;
 
+  hardeningDisable = [ "stackprotector" "fortify" "pic" ];
 
+  buildInputs = [
+    cmake pkgconfig which
 
-stdenv.mkDerivation {
-  inherit (xenConfig) name version src;
+    # Xen
+    bison bzip2 checkpolicy dev86 figlet flex gettext glib iasl libaio
+    libiconv libuuid ncurses openssl perl python2Packages.python xz yajl zlib
 
-  dontUseCmakeConfigure = true;
+    # oxenstored
+    ocamlPackages.findlib ocamlPackages.ocaml
 
-  buildInputs =
-    [ which zlib pkgconfig SDL openssl libuuid gettext ncurses
-      dev86 iasl pciutils bzip2 xz texinfo perl yajl
-      python2Packages.python python2Packages.wrapPython
-      glib bridge-utils pixman iproute udev bison xorg.libX11
-      flex ocamlPackages.ocaml ocamlPackages.findlib figlet libaio
-      checkpolicy python2Packages.markdown transfig
-      glusterfs acl cmake spice spice_protocol usbredir
-      alsaLib quilt
-    ];
+    # Python fixes
+    python2Packages.wrapPython
 
-  hardeningDisable = [ "stackprotector" "fortify" "pic" ];
+    # Documentation
+    python2Packages.markdown transfig ghostscript texinfo pandoc
 
-  patches = stdenv.lib.optionals ((xenserverPatched == false) && (builtins.hasAttr "xenPatches" xenConfig)) xenConfig.xenPatches;
+    # Others
+  ] ++ (concatMap (x: x.buildInputs or []) (attrValues config.xenfiles))
+    ++ (config.buildInputs or []);
 
-  postPatch = ''
-      ${stdenv.lib.optionalString ((xenserverPatched == true) && (builtins.hasAttr "xenserverPatches" xenConfig)) xenConfig.xenserverPatches}
-
-      # Xen's tools and firmares need various git repositories that it
-      # usually checks out at time using git.  We can't have that.
-      ${flip concatMapStrings xenConfig.toolsGits (x: let src = fetchgit x.git; in ''
-        cp -r ${src} tools/${src.name}-dir-remote
-        chmod -R +w tools/${src.name}-dir-remote
-      '' + stdenv.lib.optionalString (builtins.hasAttr "patches" x) ''
-        ( cd tools/${src.name}-dir-remote; ${concatStringsSep "; " (map (p: "patch -p1 < ${p}") x.patches)} )
-      '')}
-      ${flip concatMapStrings xenConfig.firmwareGits (x: let src = fetchgit x.git; in ''
-        cp -r ${src} tools/firmware/${src.name}-dir-remote
-        chmod -R +w tools/firmware/${src.name}-dir-remote
-      '' + stdenv.lib.optionalString (builtins.hasAttr "patches" x) ''
-        ( cd tools/firmware/${src.name}-dir-remote; ${concatStringsSep "; " (map (p: "patch -p1 < ${p}") x.patches)} )
-      '')}
-
-      # Xen's stubdoms and firmwares need various sources that are usually fetched
-      # at build time using wget. We can't have that, so we prefetch Xen's ext_files.
-      mkdir xen_ext_files
-      ${flip concatMapStrings xenExtfiles (x: let src = fetchurl x; in ''
-        cp ${src} xen_ext_files/${src.name}
-      '')}
-
-      # Avoid a glibc >= 2.25 deprecation warnings that get fatal via -Werror.
-      sed 1i'#include <sys/sysmacros.h>' \
-        -i tools/blktap2/control/tap-ctl-allocate.c \
-        -i tools/libxl/libxl_device.c
-  '';
+  prePatch = ''
+    ### Generic fixes
+
+    # Xen's stubdoms, tools and firmwares need various sources that
+    # are usually fetched at build time using wget and git. We can't
+    # have that, so we prefetch them in nix-expression and setup
+    # fake wget and git for debugging purposes.
+
+    mkdir fake-bin
+
+    # Fake git: just print what it wants and die
+    cat > fake-bin/wget << EOF
+    #!/bin/sh -e
+    echo ===== FAKE WGET: Not fetching \$*
+    [ -e \$3 ]
+    EOF
 
-  preConfigure = ''
-    # Fake wget: copy prefetched downloads instead
-    mkdir wget
-    echo "#!/bin/sh" > wget/wget
-    echo "echo ===== Not fetching \$*, copy pre-fetched file instead" >> wget/wget
-    echo "cp \$4 \$3" >> wget/wget
-    chmod +x wget/wget
-    export PATH=$PATH:$PWD/wget
-    export EXTRA_QEMUU_CONFIGURE_ARGS="--enable-spice --enable-usb-redir --enable-linux-aio"
+    # Fake git: just print what it wants and die
+    cat > fake-bin/git << EOF
+    #!/bin/sh
+    echo ===== FAKE GIT: Not cloning \$*
+    [ -e \$3 ]
+    EOF
+
+    chmod +x fake-bin/*
+    export PATH=$PATH:$PWD/fake-bin
+
+    # Remove in-tree qemu stuff in case we build from a tar-ball
+    rm -rf tools/qemu-xen tools/qemu-xen-traditional
+
+    # Fix shebangs, mainly for build-scipts
+    # We want to do this before getting prefetched stuff to speed things up
+    # (prefetched stuff has lots of files)
+    find . -type f | xargs sed -i 's@/usr/bin/\(python\|perl\)@/usr/bin/env \1@g'
+    find . -type f | xargs sed -i 's@/bin/bash@/bin/sh@g'
+
+    # Get prefetched stuff
+    ${withXenfiles (name: x: ''
+      echo "${x.src} -> tools/${name}"
+      cp -r ${x.src} tools/${name}
+      chmod -R +w tools/${name}
+    '')}
   '';
 
-  # https://github.com/NixOS/nixpkgs/issues/13590
-  configureFlags = ["--disable-stubdom"];
+  patches = [ ./0000-fix-ipxe-src.patch
+              ./0000-fix-install-python.patch ]
+         ++ (config.patches or []);
 
-  postConfigure =
-    ''
-      substituteInPlace tools/libfsimage/common/fsimage_plugin.c \
-        --replace /usr $out
+  postPatch = ''
+    ### Hacks
+
+    # Work around a bug in our GCC wrapper: `gcc -MF foo -v' doesn't
+    # print the GCC version number properly.
+    substituteInPlace xen/Makefile \
+      --replace '$(CC) $(CFLAGS) -v' '$(CC) -v'
 
-      substituteInPlace tools/blktap2/lvm/lvm-util.c \
-        --replace /usr/sbin/vgs ${lvm2}/sbin/vgs \
-        --replace /usr/sbin/lvs ${lvm2}/sbin/lvs
+    # Hack to get `gcc -m32' to work without having 32-bit Glibc headers.
+    mkdir -p tools/include/gnu
+    touch tools/include/gnu/stubs-32.h
 
-      substituteInPlace tools/xenmon/xenmon.py \
-        --replace /usr/bin/pkill ${procps}/bin/pkill
+    ### Fixing everything else
 
-      substituteInPlace tools/xenstat/Makefile \
-        --replace /usr/include/curses.h ${ncurses.dev}/include/curses.h
+    substituteInPlace tools/libfsimage/common/fsimage_plugin.c \
+      --replace /usr $out
 
-      substituteInPlace tools/qemu-xen-traditional/xen-hooks.mak \
-        --replace /usr/include/pci ${pciutils}/include/pci
+    substituteInPlace tools/blktap2/lvm/lvm-util.c \
+      --replace /usr/sbin/vgs ${lvm2}/bin/vgs \
+      --replace /usr/sbin/lvs ${lvm2}/bin/lvs
 
-      substituteInPlace tools/qemu-xen-traditional-dir-remote/xen-hooks.mak \
-        --replace /usr/include/pci ${pciutils}/include/pci
+    substituteInPlace tools/misc/xenpvnetboot \
+      --replace /usr/sbin/mount ${utillinux}/bin/mount \
+      --replace /usr/sbin/umount ${utillinux}/bin/umount
 
-      substituteInPlace tools/hotplug/Linux/xen-backend.rules \
-        --replace /etc/xen/scripts $out/etc/xen/scripts
+    substituteInPlace tools/xenmon/xenmon.py \
+      --replace /usr/bin/pkill ${procps}/bin/pkill
 
-      # blktap is not provided by xen, but by xapi
-      sed -i '/blktap/d' tools/hotplug/Linux/xen-backend.rules
+    substituteInPlace tools/xenstat/Makefile \
+      --replace /usr/include/curses.h ${ncurses.dev}/include/curses.h
 
-      # Work around a bug in our GCC wrapper: `gcc -MF foo -v' doesn't
-      # print the GCC version number properly.
-      substituteInPlace xen/Makefile \
-        --replace '$(CC) $(CFLAGS) -v' '$(CC) -v'
+    # TODO: use this as a template and support our own if-up scripts instead?
+    substituteInPlace tools/hotplug/Linux/xen-backend.rules.in \
+      --replace "@XEN_SCRIPT_DIR@" $out/etc/xen/scripts
 
-      # Allow the location of the xendomains config file to be
-      # overriden at runtime.
-      substituteInPlace tools/hotplug/Linux/init.d/xendomains \
-        --replace 'XENDOM_CONFIG=/etc/sysconfig/xendomains' "" \
-        --replace 'XENDOM_CONFIG=/etc/default/xendomains' "" \
-        --replace /etc/xen/scripts/hotplugpath.sh $out/etc/xen/scripts/hotplugpath.sh \
-        --replace /bin/ls ls
+    # blktap is not provided by xen, but by xapi
+    sed -i '/blktap/d' tools/hotplug/Linux/xen-backend.rules.in
 
-      substituteInPlace tools/hotplug/Linux/xendomains \
-        --replace /bin/ls ls
+    ${withTools "patches" (name: x: ''
+      ${concatMapStringsSep "\n" (p: ''
+        echo "# Patching with ${p}"
+        patch -p1 < ${p}
+      '') x.patches}
+    '')}
 
-      # Hack to get `gcc -m32' to work without having 32-bit Glibc headers.
-      mkdir -p tools/include/gnu
-      touch tools/include/gnu/stubs-32.h
-    '';
+    ${withTools "postPatch" (name: x: x.postPatch)}
 
-  # Fix build on Glibc 2.24.
-  NIX_CFLAGS_COMPILE = "-Wno-error=deprecated-declarations";
+    ${config.postPatch or ""}
+  '';
 
   # TODO: Flask needs more testing before enabling it by default.
   #makeFlags = "XSM_ENABLE=y FLASK_ENABLE=y PREFIX=$(out) CONFIG_DIR=/etc XEN_EXTFILES_URL=\\$(XEN_ROOT)/xen_ext_files ";
-  makeFlags = "PREFIX=$(out) CONFIG_DIR=/etc XEN_EXTFILES_URL=\\$(XEN_ROOT)/xen_ext_files ";
+  makeFlags = [ "PREFIX=$(out) CONFIG_DIR=/etc" "XEN_SCRIPT_DIR=/etc/xen/scripts" ]
+           ++ (config.makeFlags or []);
 
   buildFlags = "xen tools";
 
-  postBuild =
-    ''
-      make -C docs man-pages
-
-      (cd tools/xen-libhvm-dir-remote; make)
-      (cd tools/xen-libhvm-dir-remote/biospt; cc -Wall -g -D_LINUX -Wstrict-prototypes biospt.c -o biospt -I../libhvm -L../libhvm -lxenhvm)
-    '';
-
-  installPhase =
-    ''
-      mkdir -p $out $out/share
-      cp -prvd dist/install/nix/store/*/* $out/
-      cp -prvd dist/install/boot $out/boot
-      cp -prvd dist/install/etc $out
-      cp -dR docs/man1 docs/man5 $out/share/man/
-      wrapPythonPrograms
-      substituteInPlace $out/etc/xen/scripts/hotplugpath.sh --replace SBINDIR=\"$out/sbin\" SBINDIR=\"$out/bin\"
-
-      shopt -s extglob
-      for i in $out/etc/xen/scripts/!(*.sh); do
-        sed -i "2s@^@export PATH=$out/bin:${scriptEnvPath}\n@" $i
-      done
-
-      (cd tools/xen-libhvm-dir-remote; make install)
-      cp tools/xen-libhvm-dir-remote/biospt/biospt $out/bin/.
-    '';
+  postBuild = ''
+    make -C docs man-pages
+
+    ${withTools "buildPhase" (name: x: x.buildPhase)}
+  '';
+
+  installPhase = ''
+    mkdir -p $out $out/share
+    cp -prvd dist/install/nix/store/*/* $out/
+    cp -prvd dist/install/boot $out/boot
+    cp -prvd dist/install/etc $out
+    cp -dR docs/man1 docs/man5 $out/share/man/
+
+    ${withTools "installPhase" (name: x: x.installPhase)}
+
+    # Hack
+    substituteInPlace $out/etc/xen/scripts/hotplugpath.sh \
+      --replace SBINDIR=\"$out/sbin\" SBINDIR=\"$out/bin\"
+
+    wrapPythonPrograms
+
+    shopt -s extglob
+    for i in $out/etc/xen/scripts/!(*.sh); do
+      sed -i "2s@^@export PATH=$out/bin:${scriptEnvPath}\n@" $i
+    done
+  '';
 
   meta = {
     homepage = http://www.xen.org/;
-    description = "Xen hypervisor and management tools for Dom0";
+    description = "Xen hypervisor and related components"
+                + optionalString (args ? meta && args.meta ? description)
+                                 " (${args.meta.description})";
+    longDescription = (args.meta.longDescription or "")
+                    + "\nIncludes:\n"
+                    + withXenfiles (name: x: ''* ${name}: ${x.meta.description or "(No description)"}.'');
     platforms = [ "x86_64-linux" ];
-    maintainers = with stdenv.lib.maintainers; [ eelco tstrobel ];
+    maintainers = with stdenv.lib.maintainers; [ eelco tstrobel oxij ];
   };
-}
+} // removeAttrs config [ "xenfiles" "buildInputs" "patches" "postPatch" "meta" ])
diff --git a/pkgs/applications/virtualization/xen/packages.nix b/pkgs/applications/virtualization/xen/packages.nix
new file mode 100644
index 000000000000..633ec4f3d124
--- /dev/null
+++ b/pkgs/applications/virtualization/xen/packages.nix
@@ -0,0 +1,64 @@
+{ callPackage
+, stdenv, overrideCC, gcc49
+}:
+
+# TODO on new Xen version: generalize this to generate [vanilla slim
+# light] for each ./<version>.nix.
+
+rec {
+
+  xen_4_5-vanilla = callPackage ./4.5.nix {
+    # At the very least included seabios and etherboot need gcc49,
+    # so we have to build all of it with gcc49.
+    stdenv = overrideCC stdenv gcc49;
+
+    meta = {
+      description = "vanilla";
+      longDescription = ''
+        Vanilla version of Xen. Uses forks of Qemu and Seabios bundled
+        with Xen. This gives vanilla experince, but wastes space and
+        build time: typical NixOS setup that runs lots of VMs will
+        build three different versions of Qemu when using this (two
+        forks and upstream).
+      '';
+    };
+  };
+
+  xen_4_5-slim = xen_4_5-vanilla.override {
+    withInternalQemu = false;
+    withInternalTraditionalQemu = true;
+    withInternalSeabios = false;
+    withSeabios = true;
+
+    meta = {
+      description = "slim";
+      longDescription = ''
+        Slimmed-down version of Xen that reuses nixpkgs packages as
+        much as possible. Different parts may get out of sync, but
+        this builds faster and uses less space than vanilla. Use with
+        `qemu_xen` from nixpkgs.
+      '';
+    };
+  };
+
+  xen_4_5-light = xen_4_5-vanilla.override {
+    withInternalQemu = false;
+    withInternalTraditionalQemu = false;
+    withInternalSeabios = false;
+    withSeabios = true;
+
+    meta = {
+      description = "light";
+      longDescription = ''
+        Slimmed-down version of Xen without `qemu-traditional` (you
+        don't need it if you don't know what it is). Use with
+        `qemu_xen-light` from nixpkgs.
+      '';
+    };
+  };
+
+  xen-vanilla = xen_4_5-vanilla;
+  xen-slim = xen_4_5-slim;
+  xen-light = xen_4_5-light;
+
+}
diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix
index 34c48c592130..cb36781ff554 100644
--- a/pkgs/top-level/all-packages.nix
+++ b/pkgs/top-level/all-packages.nix
@@ -11912,6 +11912,12 @@ with pkgs;
   watch = callPackage ../os-specific/linux/procps/watch.nix { };
 
   qemu_kvm = lowPrio (qemu.override { x86Only = true; });
+
+  # See `xenPackages` source for explanations.
+  # Building with `xen` instead of `xen-slim` is possible, but makes no sense.
+  qemu_xen = lowPrio (qemu.override { x86Only = true; xenSupport = true; xen = xen-slim; });
+  qemu_xen-light = lowPrio (qemu.override { x86Only = true; xenSupport = true; xen = xen-light; });
+
   qemu_test = lowPrio (qemu.override { x86Only = true; nixosTestRunner = true; });
 
   firmwareLinuxNonfree = callPackage ../os-specific/linux/firmware/firmware-linux-nonfree { };
@@ -16029,9 +16035,11 @@ with pkgs;
 
   xdotool = callPackage ../tools/X11/xdotool { };
 
-  xen_4_5 = callPackage ../applications/virtualization/xen/4.5.nix { stdenv = overrideCC stdenv gcc49; };
-  xen_xenServer = callPackage ../applications/virtualization/xen/4.5.nix { xenserverPatched = true; stdenv = overrideCC stdenv gcc49; };
-  xen = xen_4_5;
+  xenPackages = recurseIntoAttrs (callPackage ../applications/virtualization/xen/packages.nix {});
+
+  xen = xenPackages.xen_4_5-vanilla;
+  xen-slim = xenPackages.xen_4_5-slim;
+  xen-light = xenPackages.xen_4_5-light;
 
   win-spice = callPackage ../applications/virtualization/driver/win-spice { };
   win-virtio = callPackage ../applications/virtualization/driver/win-virtio { };