[Pkg-xen-changes] [xen] 02/37: Import xen_4.5.1~rc2.orig.tar.xz

Ian James Campbell ijc at moszumanska.debian.org
Sat Aug 22 09:13:42 UTC 2015


This is an automated email from the git hooks/post-receive script.

ijc pushed a commit to branch feature/4.5.1_rc2
in repository xen.

commit d3ec56fe36b97ca47c68256ad04747cb89684d31
Author: Ian Campbell <ijc at debian.org>
Date:   Sat Aug 22 09:24:35 2015 +0100

    Import xen_4.5.1~rc2.orig.tar.xz
---
 Config.mk                                        |  8 +-
 tools/console/daemon/main.c                      | 38 ++++++++++
 tools/hotplug/Linux/systemd/xenstored.service.in |  1 +
 tools/libxl/libxl.c                              | 77 +++++++++++++++----
 tools/libxl/libxl_internal.h                     |  1 +
 tools/ocaml/libs/xc/xenctrl_stubs.c              | 83 ++++++++++++++++-----
 tools/tests/x86_emulator/test_x86_emulator.c     |  2 +-
 xen/Makefile                                     |  2 +-
 xen/arch/x86/dmi_scan.c                          | 67 ++++++++++-------
 xen/arch/x86/domain.c                            | 11 ++-
 xen/arch/x86/e820.c                              | 18 +++--
 xen/arch/x86/efi/runtime.h                       |  7 ++
 xen/arch/x86/efi/stub.c                          |  3 +
 xen/arch/x86/hvm/hvm.c                           | 10 ++-
 xen/arch/x86/io_apic.c                           |  4 +
 xen/arch/x86/irq.c                               | 11 ++-
 xen/arch/x86/mm.c                                |  5 +-
 xen/arch/x86/traps.c                             |  2 +-
 xen/arch/x86/x86_emulate/x86_emulate.c           |  3 +-
 xen/common/cpupool.c                             | 95 +++++++++++++++++-------
 xen/common/symbols.c                             |  2 +-
 xen/drivers/passthrough/amd/iommu_intr.c         |  6 +-
 xen/include/asm-x86/page.h                       |  1 +
 xen/include/xen/dmi.h                            |  2 +-
 24 files changed, 344 insertions(+), 115 deletions(-)

diff --git a/Config.mk b/Config.mk
index b9a89a1..7c1670f 100644
--- a/Config.mk
+++ b/Config.mk
@@ -252,7 +252,7 @@ QEMU_TRADITIONAL_URL ?= git://xenbits.xen.org/qemu-xen-4.5-testing.git
 SEABIOS_UPSTREAM_URL ?= git://xenbits.xen.org/seabios.git
 endif
 OVMF_UPSTREAM_REVISION ?= 447d264115c476142f884af0be287622cd244423
-QEMU_UPSTREAM_REVISION ?= qemu-xen-4.5.1-rc1
+QEMU_UPSTREAM_REVISION ?= qemu-xen-4.5.1-rc2
 SEABIOS_UPSTREAM_REVISION ?= rel-1.7.5
 # Thu May 22 16:59:16 2014 -0400
 # python3 fixes for vgabios and csm builds.
@@ -260,9 +260,9 @@ SEABIOS_UPSTREAM_REVISION ?= rel-1.7.5
 ETHERBOOT_NICS ?= rtl8139 8086100e
 
 
-QEMU_TRADITIONAL_REVISION ?= xen-4.5.1-rc1
-# Tue Mar 31 16:27:45 2015 +0100
-# xen: limit guest control of PCI command register
+QEMU_TRADITIONAL_REVISION ?= xen-4.5.1-rc2
+# Wed May 6 09:48:59 2015 +0200
+# fdc: force the fifo access to be in bounds of the allocated buffer
 
 # Specify which qemu-dm to use. This may be `ioemu' to use the old
 # Mercurial in-tree version, or a local directory, or a git URL.
diff --git a/tools/console/daemon/main.c b/tools/console/daemon/main.c
index 92d2fc4..11de5c9 100644
--- a/tools/console/daemon/main.c
+++ b/tools/console/daemon/main.c
@@ -26,6 +26,7 @@
 #include <string.h>
 #include <signal.h>
 #include <sys/types.h>
+#include <sys/resource.h>
 
 #include "xenctrl.h"
 
@@ -55,6 +56,41 @@ static void version(char *name)
 	printf("Xen Console Daemon 3.0\n");
 }
 
+static void increase_fd_limit(void)
+{
+	/*
+	 * We require many file descriptors:
+	 * - per domain: pty master, pty slave, logfile and evtchn
+	 * - misc extra: hypervisor log, privcmd, gntdev, std...
+	 *
+	 * Allow a generous 1000 for misc, and calculate the maximum possible
+	 * number of fds which could be used.
+	 */
+	unsigned min_fds = (DOMID_FIRST_RESERVED * 4) + 1000;
+	struct rlimit lim, new = { min_fds, min_fds };
+
+	if (getrlimit(RLIMIT_NOFILE, &lim) < 0) {
+		fprintf(stderr, "Failed to obtain fd limit: %s\n",
+			strerror(errno));
+		exit(1);
+	}
+
+	/* Do we already have sufficient? Great! */
+	if (lim.rlim_cur >= min_fds)
+		return;
+
+	/* Try to increase our limit. */
+	if (setrlimit(RLIMIT_NOFILE, &new) < 0)
+		syslog(LOG_WARNING,
+		       "Unable to increase fd limit from {%llu, %llu} to "
+		       "{%llu, %llu}: (%s) - May run out with lots of domains",
+		       (unsigned long long)lim.rlim_cur,
+		       (unsigned long long)lim.rlim_max,
+		       (unsigned long long)new.rlim_cur,
+		       (unsigned long long)new.rlim_max,
+		       strerror(errno));
+}
+
 int main(int argc, char **argv)
 {
 	const char *sopts = "hVvit:o:";
@@ -154,6 +190,8 @@ int main(int argc, char **argv)
 	openlog("xenconsoled", syslog_option, LOG_DAEMON);
 	setlogmask(syslog_mask);
 
+	increase_fd_limit();
+
 	if (!is_interactive) {
 		daemonize(pidfile ? pidfile : "/var/run/xenconsoled.pid");
 	}
diff --git a/tools/hotplug/Linux/systemd/xenstored.service.in b/tools/hotplug/Linux/systemd/xenstored.service.in
index 0f0ac58..a5f836b 100644
--- a/tools/hotplug/Linux/systemd/xenstored.service.in
+++ b/tools/hotplug/Linux/systemd/xenstored.service.in
@@ -8,6 +8,7 @@ ConditionPathExists=/proc/xen/capabilities
 
 [Service]
 Type=notify
+KillMode=none
 Environment=XENSTORED_ARGS=
 Environment=XENSTORED=@XENSTORED@
 EnvironmentFile=- at CONFIG_DIR@/@CONFIG_LEAF_DIR@/xencommons
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 372dd3b..1f4dce2 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -1158,22 +1158,20 @@ static void domain_death_xswatch_callback(libxl__egc *egc, libxl__ev_xswatch *w,
                                         const char *wpath, const char *epath) {
     EGC_GC;
     libxl_evgen_domain_death *evg;
-    uint32_t domid;
     int rc;
 
     CTX_LOCK;
 
     evg = LIBXL_TAILQ_FIRST(&CTX->death_list);
-    if (!evg) goto out;
-
-    domid = evg->domid;
 
     for (;;) {
+        if (!evg) goto out;
+
         int nentries = LIBXL_TAILQ_NEXT(evg, entry) ? 200 : 1;
         xc_domaininfo_t domaininfos[nentries];
         const xc_domaininfo_t *got = domaininfos, *gotend;
 
-        rc = xc_domain_getinfolist(CTX->xch, domid, nentries, domaininfos);
+        rc = xc_domain_getinfolist(CTX->xch, evg->domid, nentries, domaininfos);
         if (rc == -1) {
             LIBXL__EVENT_DISASTER(egc, "xc_domain_getinfolist failed while"
                                   " processing @releaseDomain watch event",
@@ -1183,8 +1181,10 @@ static void domain_death_xswatch_callback(libxl__egc *egc, libxl__ev_xswatch *w,
         gotend = &domaininfos[rc];
 
         LIBXL__LOG(CTX, LIBXL__LOG_DEBUG, "[evg=%p:%"PRIu32"]"
-                   " from domid=%"PRIu32" nentries=%d rc=%d",
-                   evg, evg->domid, domid, nentries, rc);
+                   " nentries=%d rc=%d %ld..%ld",
+                   evg, evg->domid, nentries, rc,
+                   rc>0 ? (long)domaininfos[0].domain : 0,
+                   rc>0 ? (long)domaininfos[rc-1].domain : 0);
 
         for (;;) {
             if (!evg) {
@@ -1247,7 +1247,6 @@ static void domain_death_xswatch_callback(libxl__egc *egc, libxl__ev_xswatch *w,
         }
 
         assert(rc); /* rc==0 results in us eating all evgs and quitting */
-        domid = gotend[-1].domain;
     }
  all_reported:
  out:
@@ -1549,6 +1548,10 @@ static void devices_destroy_cb(libxl__egc *egc,
                                libxl__devices_remove_state *drs,
                                int rc);
 
+static void domain_destroy_domid_cb(libxl__egc *egc,
+                                    libxl__ev_child *destroyer,
+                                    pid_t pid, int status);
+
 void libxl__destroy_domid(libxl__egc *egc, libxl__destroy_domid_state *dis)
 {
     STATE_AO_GC(dis->ao);
@@ -1558,6 +1561,8 @@ void libxl__destroy_domid(libxl__egc *egc, libxl__destroy_domid_state *dis)
     char *pid;
     int rc, dm_present;
 
+    libxl__ev_child_init(&dis->destroyer);
+
     rc = libxl_domain_info(ctx, NULL, domid);
     switch(rc) {
     case 0:
@@ -1627,7 +1632,7 @@ static void devices_destroy_cb(libxl__egc *egc,
     uint32_t domid = dis->domid;
     char *dom_path;
     char *vm_path;
-    libxl__domain_userdata_lock *lock = NULL;
+    libxl__domain_userdata_lock *lock;
 
     dom_path = libxl__xs_get_dompath(gc, domid);
     if (!dom_path) {
@@ -1661,18 +1666,60 @@ static void devices_destroy_cb(libxl__egc *egc,
     }
     libxl__userdata_destroyall(gc, domid);
 
-    rc = xc_domain_destroy(ctx->xch, domid);
-    if (rc < 0) {
-        LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc, "xc_domain_destroy failed for %d", domid);
+    libxl__unlock_domain_userdata(lock);
+
+    rc = libxl__ev_child_fork(gc, &dis->destroyer, domain_destroy_domid_cb);
+    if (rc < 0) goto out;
+    if (!rc) { /* child */
+        ctx->xch = xc_interface_open(ctx->lg,0,0);
+        if (!ctx->xch) goto badchild;
+
+        rc = xc_domain_destroy(ctx->xch, domid);
+        if (rc < 0) goto badchild;
+        _exit(0);
+
+    badchild:
+        if (errno > 0  && errno < 126) {
+            _exit(errno);
+        } else {
+            LOGE(ERROR,
+ "xc_domain_destroy failed for %d (with difficult errno value %d)",
+                 domid, errno);
+            _exit(-1);
+        }
+    }
+    LOG(INFO, "forked pid %ld for destroy of domain %d", (long)rc, domid);
+
+    return;
+
+out:
+    dis->callback(egc, dis, rc);
+    return;
+}
+
+static void domain_destroy_domid_cb(libxl__egc *egc,
+                                    libxl__ev_child *destroyer,
+                                    pid_t pid, int status)
+{
+    libxl__destroy_domid_state *dis = CONTAINER_OF(destroyer, *dis, destroyer);
+    STATE_AO_GC(dis->ao);
+    int rc;
+
+    if (status) {
+        if (WIFEXITED(status) && WEXITSTATUS(status)<126) {
+            LOGEV(ERROR, WEXITSTATUS(status),
+                  "xc_domain_destroy failed for %"PRIu32"", dis->domid);
+        } else {
+            libxl_report_child_exitstatus(CTX, XTL_ERROR,
+                                          "async domain destroy", pid, status);
+        }
         rc = ERROR_FAIL;
         goto out;
     }
     rc = 0;
 
-out:
-    if (lock) libxl__unlock_domain_userdata(lock);
+ out:
     dis->callback(egc, dis, rc);
-    return;
 }
 
 int libxl_console_exec(libxl_ctx *ctx, uint32_t domid, int cons_num,
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 6dac0f8..a1624fd 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -2957,6 +2957,7 @@ struct libxl__destroy_domid_state {
     libxl__domid_destroy_cb *callback;
     /* private to implementation */
     libxl__devices_remove_state drs;
+    libxl__ev_child destroyer;
 };
 
 struct libxl__domain_destroy_state {
diff --git a/tools/ocaml/libs/xc/xenctrl_stubs.c b/tools/ocaml/libs/xc/xenctrl_stubs.c
index f0810eb..64f1137 100644
--- a/tools/ocaml/libs/xc/xenctrl_stubs.c
+++ b/tools/ocaml/libs/xc/xenctrl_stubs.c
@@ -51,21 +51,22 @@
 	i1 = (uint32_t) Int64_val(Field(input, 0)); \
 	i2 = ((Field(input, 1) == Val_none) ? 0xffffffff : (uint32_t) Int64_val(Field(Field(input, 1), 0)));
 
-#define ERROR_STRLEN 1024
-void failwith_xc(xc_interface *xch)
+static void Noreturn failwith_xc(xc_interface *xch)
 {
-	static char error_str[ERROR_STRLEN];
+	char error_str[256];
 	if (xch) {
 		const xc_error *error = xc_get_last_error(xch);
 		if (error->code == XC_ERROR_NONE)
-                	snprintf(error_str, ERROR_STRLEN, "%d: %s", errno, strerror(errno));
+			snprintf(error_str, sizeof(error_str),
+				 "%d: %s", errno, strerror(errno));
 		else
-			snprintf(error_str, ERROR_STRLEN, "%d: %s: %s",
-				 error->code,
+			snprintf(error_str, sizeof(error_str),
+				 "%d: %s: %s", error->code,
 				 xc_error_code_to_desc(error->code),
 				 error->message);
 	} else {
-		snprintf(error_str, ERROR_STRLEN, "Unable to open XC interface");
+		snprintf(error_str, sizeof(error_str),
+			 "Unable to open XC interface");
 	}
 	caml_raise_with_string(*caml_named_value("xc.error"), error_str);
 }
@@ -457,6 +458,9 @@ CAMLprim value stub_xc_vcpu_getaffinity(value xch, value domid,
 	int i, len = xc_get_max_cpus(_H(xch));
 	int retval;
 
+	if (len < 1)
+		failwith_xc(_H(xch));
+
 	c_cpumap = xc_cpumap_alloc(_H(xch));
 	if (c_cpumap == NULL)
 		failwith_xc(_H(xch));
@@ -526,26 +530,65 @@ CAMLprim value stub_xc_evtchn_reset(value xch, value domid)
 }
 
 
-#define RING_SIZE 32768
-static char ring[RING_SIZE];
-
 CAMLprim value stub_xc_readconsolering(value xch)
 {
-	unsigned int size = RING_SIZE - 1;
-	char *ring_ptr = ring;
-	int retval;
+	/* Safe to use outside of blocking sections because of Ocaml GC lock. */
+	static unsigned int conring_size = 16384 + 1;
+
+	unsigned int count = conring_size, size = count, index = 0;
+	char *str = NULL, *ptr;
+	int ret;
 
 	CAMLparam1(xch);
+	CAMLlocal1(ring);
 
+	str = malloc(size);
+	if (!str)
+		caml_raise_out_of_memory();
+
+	/* Hopefully our conring_size guess is sufficient */
 	caml_enter_blocking_section();
-	retval = xc_readconsolering(_H(xch), ring_ptr, &size, 0, 0, NULL);
+	ret = xc_readconsolering(_H(xch), str, &count, 0, 0, &index);
 	caml_leave_blocking_section();
 
-	if (retval)
+	if (ret < 0) {
+		free(str);
 		failwith_xc(_H(xch));
+	}
+
+	while (count == size && ret >= 0) {
+		size += count - 1;
+		if (size < count)
+			break;
 
-	ring[size] = '\0';
-	CAMLreturn(caml_copy_string(ring));
+		ptr = realloc(str, size);
+		if (!ptr)
+			break;
+
+		str = ptr + count;
+		count = size - count;
+
+		caml_enter_blocking_section();
+		ret = xc_readconsolering(_H(xch), str, &count, 0, 1, &index);
+		caml_leave_blocking_section();
+
+		count += str - ptr;
+		str = ptr;
+	}
+
+	/*
+	 * If we didn't break because of an overflow with size, and we have
+	 * needed to realloc() ourself more space, update our tracking of the
+	 * real console ring size.
+	 */
+	if (size > conring_size)
+		conring_size = size;
+
+	ring = caml_alloc_string(count);
+	memcpy(String_val(ring), str, count);
+	free(str);
+
+	CAMLreturn(ring);
 }
 
 CAMLprim value stub_xc_send_debug_keys(value xch, value keys)
@@ -821,6 +864,12 @@ CAMLprim value stub_xc_version_version(value xch)
 
 	caml_enter_blocking_section();
 	packed = xc_version(_H(xch), XENVER_version, NULL);
+	caml_leave_blocking_section();
+
+	if (packed < 0)
+		failwith_xc(_H(xch));
+
+	caml_enter_blocking_section();
 	retval = xc_version(_H(xch), XENVER_extraversion, &extra);
 	caml_leave_blocking_section();
 
diff --git a/tools/tests/x86_emulator/test_x86_emulator.c b/tools/tests/x86_emulator/test_x86_emulator.c
index 6f67fc7..347d5f9 100644
--- a/tools/tests/x86_emulator/test_x86_emulator.c
+++ b/tools/tests/x86_emulator/test_x86_emulator.c
@@ -288,7 +288,7 @@ int main(int argc, char **argv)
     rc = x86_emulate(&ctxt, &emulops);
     if ( (rc != X86EMUL_OKAY) || 
          (*res != 0x923456AA) || 
-         ((regs.eflags&0x240) != 0x200) ||
+         ((regs.eflags&0xad5) != 0xa91) ||
          (regs.eax != 0xAABBCCAA) ||
          (regs.ecx != 0xFF) ||
          (regs.eip != (unsigned long)&instr[4]) )
diff --git a/xen/Makefile b/xen/Makefile
index 5720393..a5b47f7 100644
--- a/xen/Makefile
+++ b/xen/Makefile
@@ -2,7 +2,7 @@
 # All other places this is stored (eg. compile.h) should be autogenerated.
 export XEN_VERSION       = 4
 export XEN_SUBVERSION    = 5
-export XEN_EXTRAVERSION ?= .1-rc1$(XEN_VENDORVERSION)
+export XEN_EXTRAVERSION ?= .1-rc2$(XEN_VENDORVERSION)
 export XEN_FULLVERSION   = $(XEN_VERSION).$(XEN_SUBVERSION)$(XEN_EXTRAVERSION)
 -include xen-version
 
diff --git a/xen/arch/x86/dmi_scan.c b/xen/arch/x86/dmi_scan.c
index 500133a..aaba5e7 100644
--- a/xen/arch/x86/dmi_scan.c
+++ b/xen/arch/x86/dmi_scan.c
@@ -127,6 +127,8 @@ static inline bool_t __init dmi_checksum(const void __iomem *buf,
 
 static u32 __initdata efi_dmi_address;
 static u32 __initdata efi_dmi_size;
+static u32 __initdata efi_smbios_address;
+static u32 __initdata efi_smbios_size;
 
 /*
  * Important: This function gets called while still in EFI
@@ -136,39 +138,54 @@ void __init dmi_efi_get_table(void *smbios)
 {
 	struct smbios_eps *eps = smbios;
 
-	if (memcmp(eps->anchor, "_SM_", 4) &&
-	    dmi_checksum(eps, eps->length) &&
-	    memcmp(eps->dmi.anchor, "_DMI_", 5) == 0 &&
-	    dmi_checksum(&eps->dmi, sizeof(eps->dmi))) {
-		efi_dmi_address = eps->dmi.address;
-		efi_dmi_size = eps->dmi.size;
+	if (memcmp(eps->anchor, "_SM_", 4) == 0 &&
+	    eps->length >= sizeof(*eps) &&
+	    dmi_checksum(eps, eps->length)) {
+		efi_smbios_address = (u32)(long)eps;
+		efi_smbios_size = eps->length;
+
+		if (memcmp(eps->dmi.anchor, "_DMI_", 5) == 0 &&
+		    dmi_checksum(&eps->dmi, sizeof(eps->dmi))) {
+			efi_dmi_address = eps->dmi.address;
+			efi_dmi_size = eps->dmi.size;
+		}
 	}
 }
 
-int __init dmi_get_table(u32 *base, u32 *len)
+const char *__init dmi_get_table(paddr_t *base, u32 *len)
 {
-	struct dmi_eps eps;
-	char __iomem *p, *q;
+	static unsigned int __initdata instance;
 
 	if (efi_enabled) {
-		if (!efi_dmi_size)
-			return -1;
-		*base = efi_dmi_address;
-		*len = efi_dmi_size;
-		return 0;
-	}
-
-	p = maddr_to_virt(0xF0000);
-	for (q = p; q < p + 0x10000; q += 16) {
-		memcpy_fromio(&eps, q, 15);
-		if (memcmp(eps.anchor, "_DMI_", 5) == 0 &&
-		    dmi_checksum(&eps, sizeof(eps))) {
-			*base = eps.address;
-			*len = eps.size;
-			return 0;
+		if (efi_dmi_size && !(instance & 2)) {
+			*base = efi_dmi_address;
+			*len = efi_dmi_size;
+			instance |= 2;
+			return "DMI";
+		}
+		if (efi_smbios_size && !(instance & 4)) {
+			*base = efi_smbios_address;
+			*len = efi_smbios_size;
+			instance |= 4;
+			return "SMBIOS";
+		}
+	} else {
+		char __iomem *p = maddr_to_virt(0xF0000), *q;
+		struct dmi_eps eps;
+
+		for (q = p; q <= p + 0x10000 - sizeof(eps); q += 16) {
+			memcpy_fromio(&eps, q, sizeof(eps));
+			if (!(instance & 1) &&
+			    memcmp(eps.anchor, "_DMI_", 5) == 0 &&
+			    dmi_checksum(&eps, sizeof(eps))) {
+				*base = eps.address;
+				*len = eps.size;
+				instance |= 1;
+				return "DMI";
+			}
 		}
 	}
-	return -1;
+	return NULL;
 }
 
 static int __init _dmi_iterate(const struct dmi_eps *dmi,
diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
index f1fc993..61deaff 100644
--- a/xen/arch/x86/domain.c
+++ b/xen/arch/x86/domain.c
@@ -519,12 +519,6 @@ int arch_domain_create(struct domain *d, unsigned int domcr_flags)
     int i, paging_initialised = 0;
     int rc = -ENOMEM;
 
-    d->arch.hvm_domain.hap_enabled =
-        has_hvm_container_domain(d) &&
-        hvm_funcs.hap_supported &&
-        (domcr_flags & DOMCRF_hap);
-    d->arch.hvm_domain.mem_sharing_enabled = 0;
-
     d->arch.s3_integrity = !!(domcr_flags & DOMCRF_s3_integrity);
 
     INIT_LIST_HEAD(&d->arch.pdev_list);
@@ -547,7 +541,12 @@ int arch_domain_create(struct domain *d, unsigned int domcr_flags)
     }
 
     if ( has_hvm_container_domain(d) )
+    {
+        d->arch.hvm_domain.hap_enabled =
+            hvm_funcs.hap_supported && (domcr_flags & DOMCRF_hap);
+
         rc = create_perdomain_mapping(d, PERDOMAIN_VIRT_START, 0, NULL, NULL);
+    }
     else if ( is_idle_domain(d) )
         rc = 0;
     else
diff --git a/xen/arch/x86/e820.c b/xen/arch/x86/e820.c
index bf84bae..743a375 100644
--- a/xen/arch/x86/e820.c
+++ b/xen/arch/x86/e820.c
@@ -504,11 +504,19 @@ static uint64_t __init mtrr_top_of_ram(void)
 
 static void __init reserve_dmi_region(void)
 {
-    u32 base, len;
-    if ( (dmi_get_table(&base, &len) == 0) && ((base + len) > base) &&
-         reserve_e820_ram(&e820, base, base + len) )
-        printk("WARNING: DMI table located in E820 RAM %08x-%08x. Fixed.\n",
-               base, base+len);
+    for ( ; ; )
+    {
+        paddr_t base;
+        u32 len;
+        const char *what = dmi_get_table(&base, &len);
+
+        if ( !what )
+            break;
+        if ( ((base + len) > base) &&
+             reserve_e820_ram(&e820, base, base + len) )
+            printk("WARNING: %s table located in E820 RAM %"PRIpaddr"-%"PRIpaddr". Fixed.\n",
+                   what, base, base + len);
+    }
 }
 
 static void __init machine_specific_memory_setup(
diff --git a/xen/arch/x86/efi/runtime.h b/xen/arch/x86/efi/runtime.h
index 0eb2fb9..d9eb8f5 100644
--- a/xen/arch/x86/efi/runtime.h
+++ b/xen/arch/x86/efi/runtime.h
@@ -1,5 +1,12 @@
+#include <asm/atomic.h>
 #include <asm/mc146818rtc.h>
 
 #ifndef COMPAT
 l4_pgentry_t *__read_mostly efi_l4_pgtable;
+
+void efi_update_l4_pgtable(unsigned int l4idx, l4_pgentry_t l4e)
+{
+    if ( efi_l4_pgtable )
+        l4e_write(efi_l4_pgtable + l4idx, l4e);
+}
 #endif
diff --git a/xen/arch/x86/efi/stub.c b/xen/arch/x86/efi/stub.c
index b8f49f8..627009f 100644
--- a/xen/arch/x86/efi/stub.c
+++ b/xen/arch/x86/efi/stub.c
@@ -2,6 +2,7 @@
 #include <xen/errno.h>
 #include <xen/init.h>
 #include <xen/lib.h>
+#include <asm/page.h>
 
 #ifndef efi_enabled
 const bool_t efi_enabled = 0;
@@ -9,6 +10,8 @@ const bool_t efi_enabled = 0;
 
 void __init efi_init_memory(void) { }
 
+void efi_update_l4_pgtable(unsigned int l4idx, l4_pgentry_t l4e) { }
+
 paddr_t efi_rs_page_table(void)
 {
     BUG();
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index 55077f9..7d53c6c 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -486,7 +486,7 @@ static void hvm_free_ioreq_gmfn(struct domain *d, unsigned long gmfn)
 {
     unsigned int i = gmfn - d->arch.hvm_domain.ioreq_gmfn.base;
 
-    clear_bit(i, &d->arch.hvm_domain.ioreq_gmfn.mask);
+    set_bit(i, &d->arch.hvm_domain.ioreq_gmfn.mask);
 }
 
 static void hvm_unmap_ioreq_page(struct hvm_ioreq_server *s, bool_t buf)
@@ -960,6 +960,7 @@ static int hvm_ioreq_server_init(struct hvm_ioreq_server *s, struct domain *d,
 static void hvm_ioreq_server_deinit(struct hvm_ioreq_server *s,
                                     bool_t is_default)
 {
+    ASSERT(!s->enabled);
     hvm_ioreq_server_remove_all_vcpus(s);
     hvm_ioreq_server_unmap_pages(s, is_default);
     hvm_ioreq_server_free_rangesets(s, is_default);
@@ -1062,6 +1063,8 @@ static int hvm_destroy_ioreq_server(struct domain *d, ioservid_t id)
 
         domain_pause(d);
 
+        hvm_ioreq_server_disable(s, 0);
+
         list_del(&s->list_entry);
         
         hvm_ioreq_server_deinit(s, 0);
@@ -1320,11 +1323,10 @@ static void hvm_destroy_all_ioreq_servers(struct domain *d)
     {
         bool_t is_default = (s == d->arch.hvm_domain.default_ioreq_server);
 
+        hvm_ioreq_server_disable(s, is_default);
+
         if ( is_default )
-        {
-            hvm_ioreq_server_disable(s, 1);
             d->arch.hvm_domain.default_ioreq_server = NULL;
-        }
 
         list_del(&s->list_entry);
         
diff --git a/xen/arch/x86/io_apic.c b/xen/arch/x86/io_apic.c
index 01f816b..4a053a6 100644
--- a/xen/arch/x86/io_apic.c
+++ b/xen/arch/x86/io_apic.c
@@ -2614,6 +2614,10 @@ unsigned int arch_hwdom_irqs(domid_t domid)
     if ( !domid )
         n = min(n, dom0_max_vcpus());
     n = min(nr_irqs_gsi + n * NR_DYNAMIC_VECTORS, nr_irqs);
+
+    /* Bounded by the domain pirq eoi bitmap gfn. */
+    n = min_t(unsigned int, n, PAGE_SIZE * BITS_PER_BYTE);
+
     printk("Dom%d has maximum %u PIRQs\n", domid, n);
 
     return n;
diff --git a/xen/arch/x86/irq.c b/xen/arch/x86/irq.c
index 84738e5..e7ebeff 100644
--- a/xen/arch/x86/irq.c
+++ b/xen/arch/x86/irq.c
@@ -1073,13 +1073,19 @@ bool_t cpu_has_pending_apic_eoi(void)
 static inline void set_pirq_eoi(struct domain *d, unsigned int irq)
 {
     if ( d->arch.pirq_eoi_map )
+    {
+        ASSERT(irq < PAGE_SIZE * BITS_PER_BYTE);
         set_bit(irq, d->arch.pirq_eoi_map);
+    }
 }
 
 static inline void clear_pirq_eoi(struct domain *d, unsigned int irq)
 {
     if ( d->arch.pirq_eoi_map )
+    {
+        ASSERT(irq < PAGE_SIZE * BITS_PER_BYTE);
         clear_bit(irq, d->arch.pirq_eoi_map);
+    }
 }
 
 static void set_eoi_ready(void *data);
@@ -1608,12 +1614,13 @@ int pirq_guest_bind(struct vcpu *v, struct pirq *pirq, int will_share)
         init_timer(&action->eoi_timer, irq_guest_eoi_timer_fn, desc, 0);
 
         desc->status |= IRQ_GUEST;
-        desc->status &= ~IRQ_DISABLED;
-        desc->handler->startup(desc);
 
         /* Attempt to bind the interrupt target to the correct CPU. */
         if ( !opt_noirqbalance && (desc->handler->set_affinity != NULL) )
             desc->handler->set_affinity(desc, cpumask_of(v->processor));
+
+        desc->status &= ~IRQ_DISABLED;
+        desc->handler->startup(desc);
     }
     else if ( !will_share || !action->shareable )
     {
diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
index d4965da..262d59e 100644
--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -5287,7 +5287,10 @@ static l3_pgentry_t *virt_to_xen_l3e(unsigned long v)
             spin_lock(&map_pgdir_lock);
         if ( !(l4e_get_flags(*pl4e) & _PAGE_PRESENT) )
         {
-            l4e_write(pl4e, l4e_from_paddr(__pa(pl3e), __PAGE_HYPERVISOR));
+            l4_pgentry_t l4e = l4e_from_paddr(__pa(pl3e), __PAGE_HYPERVISOR);
+
+            l4e_write(pl4e, l4e);
+            efi_update_l4_pgtable(l4_table_offset(v), l4e);
             pl3e = NULL;
         }
         if ( locking )
diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c
index 61316ba..c037b00 100644
--- a/xen/arch/x86/traps.c
+++ b/xen/arch/x86/traps.c
@@ -2174,7 +2174,7 @@ static int emulate_privileged_op(struct cpu_user_regs *regs)
             if ( op_bytes == 4 )
                 regs->eax = 0;
             else
-                regs->eax &= ~((1u << (op_bytes * 8)) - 1);
+                regs->eax &= ~((1 << (op_bytes * 8)) - 1);
             regs->eax |= guest_io_read(port, op_bytes, v, regs);
         }
         bpmatch = check_guest_io_breakpoint(v, port, op_bytes);
diff --git a/xen/arch/x86/x86_emulate/x86_emulate.c b/xen/arch/x86/x86_emulate/x86_emulate.c
index 656a06f..3e8335e 100644
--- a/xen/arch/x86/x86_emulate/x86_emulate.c
+++ b/xen/arch/x86/x86_emulate/x86_emulate.c
@@ -4346,7 +4346,8 @@ x86_emulate(
         /* Save real source value, then compare EAX against destination. */
         src.orig_val = src.val;
         src.val = _regs.eax;
-        emulate_2op_SrcV("cmp", src, dst, _regs.eflags);
+        /* cmp: %%eax - dst ==> dst and src swapped for macro invocation */
+        emulate_2op_SrcV("cmp", dst, src, _regs.eflags);
         if ( _regs.eflags & EFLG_ZF )
         {
             /* Success: write back to memory. */
diff --git a/xen/common/cpupool.c b/xen/common/cpupool.c
index cd6aab9..2a557f3 100644
--- a/xen/common/cpupool.c
+++ b/xen/common/cpupool.c
@@ -452,13 +452,17 @@ void cpupool_rm_domain(struct domain *d)
 }
 
 /*
- * called to add a new cpu to pool admin
- * we add a hotplugged cpu to the cpupool0 to be able to add it to dom0,
- * unless we are resuming from S3, in which case we put the cpu back
- * in the cpupool it was in prior to suspend.
+ * Called to add a cpu to a pool. CPUs being hot-plugged are added to pool0,
+ * as they must have been in there when unplugged.
+ *
+ * If, on the other hand, we are adding CPUs because we are resuming (e.g.,
+ * after ACPI S3) we put the cpu back in the pool where it was in prior when
+ * we suspended.
  */
-static void cpupool_cpu_add(unsigned int cpu)
+static int cpupool_cpu_add(unsigned int cpu)
 {
+    int ret = 0;
+
     spin_lock(&cpupool_lock);
     cpumask_clear_cpu(cpu, &cpupool_locked_cpus);
     cpumask_set_cpu(cpu, &cpupool_free_cpus);
@@ -471,41 +475,85 @@ static void cpupool_cpu_add(unsigned int cpu)
         {
             if ( cpumask_test_cpu(cpu, (*c)->cpu_suspended ) )
             {
-                cpupool_assign_cpu_locked(*c, cpu);
+                ret = cpupool_assign_cpu_locked(*c, cpu);
+                if ( ret )
+                    goto out;
                 cpumask_clear_cpu(cpu, (*c)->cpu_suspended);
+                break;
             }
         }
-    }
 
-    if ( cpumask_test_cpu(cpu, &cpupool_free_cpus) )
-        cpupool_assign_cpu_locked(cpupool0, cpu);
+        /*
+         * Either cpu has been found as suspended in a pool, and added back
+         * there, or it stayed free (if it did not belong to any pool when
+         * suspending), and we don't want to do anything.
+         */
+        ASSERT(cpumask_test_cpu(cpu, &cpupool_free_cpus) ||
+               cpumask_test_cpu(cpu, (*c)->cpu_valid));
+    }
+    else
+    {
+        /*
+         * If we are not resuming, we are hot-plugging cpu, and in which case
+         * we add it to pool0, as it certainly was there when hot-unplagged
+         * (or unplugging would have failed) and that is the default behavior
+         * anyway.
+         */
+        ret = cpupool_assign_cpu_locked(cpupool0, cpu);
+    }
+ out:
     spin_unlock(&cpupool_lock);
+
+    return ret;
 }
 
 /*
- * called to remove a cpu from pool admin
- * the cpu to be removed is locked to avoid removing it from dom0
- * returns failure if not in pool0
+ * Called to remove a CPU from a pool. The CPU is locked, to forbid removing
+ * it from pool0. In fact, if we want to hot-unplug a CPU, it must belong to
+ * pool0, or we fail.
+ *
+ * However, if we are suspending (e.g., to ACPI S3), we mark the CPU in such
+ * a way that it can be put back in its pool when resuming.
  */
 static int cpupool_cpu_remove(unsigned int cpu)
 {
     int ret = -EBUSY;
-    struct cpupool **c;
 
     spin_lock(&cpupool_lock);
-    if ( cpumask_test_cpu(cpu, cpupool0->cpu_valid) )
-        ret = 0;
-    else
+    if ( system_state == SYS_STATE_suspend )
     {
+        struct cpupool **c;
+
         for_each_cpupool(c)
         {
-            if ( cpumask_test_cpu(cpu, (*c)->cpu_suspended ) )
+            if ( cpumask_test_cpu(cpu, (*c)->cpu_valid ) )
             {
-                ret = 0;
+                cpumask_set_cpu(cpu, (*c)->cpu_suspended);
                 break;
             }
         }
+
+        /*
+         * Either we found cpu in a pool, or it must be free (if it has been
+         * hot-unplagged, then we must have found it in pool0). It is, of
+         * course, fine to suspend or shutdown with CPUs not assigned to a
+         * pool, and (in case of suspend) they will stay free when resuming.
+         */
+        ASSERT(cpumask_test_cpu(cpu, &cpupool_free_cpus) ||
+               cpumask_test_cpu(cpu, (*c)->cpu_suspended));
+        ASSERT(cpumask_test_cpu(cpu, &cpu_online_map) ||
+               cpumask_test_cpu(cpu, cpupool0->cpu_suspended));
+        ret = 0;
     }
+    else if ( cpumask_test_cpu(cpu, cpupool0->cpu_valid) )
+    {
+        /*
+         * If we are not suspending, we are hot-unplugging cpu, and that is
+         * allowed only for CPUs in pool0.
+         */
+        ret = 0;
+    }
+
     if ( !ret )
         cpumask_set_cpu(cpu, &cpupool_locked_cpus);
     spin_unlock(&cpupool_lock);
@@ -690,20 +738,11 @@ static int cpu_callback(
     unsigned int cpu = (unsigned long)hcpu;
     int rc = 0;
 
-    if ( system_state == SYS_STATE_suspend )
-    {
-        struct cpupool **c;
-
-        for_each_cpupool(c)
-            if ( cpumask_test_cpu(cpu, (*c)->cpu_valid ) )
-                cpumask_set_cpu(cpu, (*c)->cpu_suspended);
-    }
-
     switch ( action )
     {
     case CPU_DOWN_FAILED:
     case CPU_ONLINE:
-        cpupool_cpu_add(cpu);
+        rc = cpupool_cpu_add(cpu);
         break;
     case CPU_DOWN_PREPARE:
         rc = cpupool_cpu_remove(cpu);
diff --git a/xen/common/symbols.c b/xen/common/symbols.c
index bc2fde6..fc7c9e7 100644
--- a/xen/common/symbols.c
+++ b/xen/common/symbols.c
@@ -19,7 +19,7 @@
 #include <xen/spinlock.h>
 
 #ifdef SYMBOLS_ORIGIN
-extern const unsigned int symbols_offsets[1];
+extern const unsigned int symbols_offsets[];
 #define symbols_address(n) (SYMBOLS_ORIGIN + symbols_offsets[n])
 #else
 extern const unsigned long symbols_addresses[];
diff --git a/xen/drivers/passthrough/amd/iommu_intr.c b/xen/drivers/passthrough/amd/iommu_intr.c
index c1b76fb..18d8b5f 100644
--- a/xen/drivers/passthrough/amd/iommu_intr.c
+++ b/xen/drivers/passthrough/amd/iommu_intr.c
@@ -365,15 +365,17 @@ unsigned int amd_iommu_read_ioapic_from_ire(
     unsigned int apic, unsigned int reg)
 {
     unsigned int val = __io_apic_read(apic, reg);
+    unsigned int pin = (reg - 0x10) / 2;
+    unsigned int offset = ioapic_sbdf[IO_APIC_ID(apic)].pin_2_idx[pin];
 
-    if ( !(reg & 1) )
+    if ( !(reg & 1) && offset < INTREMAP_ENTRIES )
     {
-        unsigned int offset = val & (INTREMAP_ENTRIES - 1);
         u16 bdf = ioapic_sbdf[IO_APIC_ID(apic)].bdf;
         u16 seg = ioapic_sbdf[IO_APIC_ID(apic)].seg;
         u16 req_id = get_intremap_requestor_id(seg, bdf);
         const u32 *entry = get_intremap_entry(seg, req_id, offset);
 
+        ASSERT(offset == (val & (INTREMAP_ENTRIES - 1)));
         val &= ~(INTREMAP_ENTRIES - 1);
         val |= get_field_from_reg_u32(*entry,
                                       INT_REMAP_ENTRY_INTTYPE_MASK,
diff --git a/xen/include/asm-x86/page.h b/xen/include/asm-x86/page.h
index a8bc999..ccf0752 100644
--- a/xen/include/asm-x86/page.h
+++ b/xen/include/asm-x86/page.h
@@ -286,6 +286,7 @@ extern l2_pgentry_t l2_identmap[4*L2_PAGETABLE_ENTRIES];
 extern l1_pgentry_t l1_identmap[L1_PAGETABLE_ENTRIES],
     l1_fixmap[L1_PAGETABLE_ENTRIES];
 void paging_init(void);
+void efi_update_l4_pgtable(unsigned int l4idx, l4_pgentry_t);
 #endif /* !defined(__ASSEMBLY__) */
 
 #define _PAGE_NONE     _AC(0x000,U)
diff --git a/xen/include/xen/dmi.h b/xen/include/xen/dmi.h
index 8205893..e2fc76d 100644
--- a/xen/include/xen/dmi.h
+++ b/xen/include/xen/dmi.h
@@ -34,7 +34,7 @@ struct dmi_system_id {
 
 extern int dmi_check_system(struct dmi_system_id *list);
 extern void dmi_scan_machine(void);
-extern int dmi_get_table(u32 *base, u32 *len);
+extern const char *dmi_get_table(paddr_t *base, u32 *len);
 extern void dmi_efi_get_table(void *);
 bool_t dmi_get_date(int field, int *yearp, int *monthp, int *dayp);
 extern void dmi_end_boot(void);

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-xen/xen.git



More information about the Pkg-xen-changes mailing list