[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