diff --git a/kernel.spec b/kernel.spec index 34ff35d..5155fb1 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1977,6 +1977,12 @@ fi # ||----w | # || || %changelog +* Mon Jan 24 2011 Michael Young +- update to 2.6.38-rc +- Strip out upstream or conflicting patches from xen.next-2.6.37.patch + and xen.pcifront.fixes.patch +- Add a test patch to fix a crash on boot to xen.pcifront.fixes.patch + * Sat Jan 22 2011 Kyle McMartin 2.6.38-0.rc2.git0.1 - Linux 2.6.38-rc2 - linux-2.6-serial-460800.patch, drivers/serial => drivers/tty/serial diff --git a/xen.next-2.6.37.patch b/xen.next-2.6.37.patch index cbe8c9a..f185cbe 100644 --- a/xen.next-2.6.37.patch +++ b/xen.next-2.6.37.patch @@ -1,184 +1,3 @@ -From fb27cfbcbd2865b0e731c4aae47df71778da805e Mon Sep 17 00:00:00 2001 -From: Jeremy Fitzhardinge -Date: Wed, 25 Aug 2010 12:19:53 -0700 -Subject: [PATCH 01/43] xenfs/xenbus: report partial reads/writes correctly - -copy_(to|from)_user return the number of uncopied bytes, so a successful -return is 0, and any non-zero result indicates some degree of failure. - -Reported-by: "Jun Zhu (Intern)" -Signed-off-by: Jeremy Fitzhardinge ---- - drivers/xen/xenfs/xenbus.c | 4 ++-- - 1 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/drivers/xen/xenfs/xenbus.c b/drivers/xen/xenfs/xenbus.c -index 9d5b519..d2a9058 100644 ---- a/drivers/xen/xenfs/xenbus.c -+++ b/drivers/xen/xenfs/xenbus.c -@@ -142,7 +142,7 @@ static ssize_t xenbus_file_read(struct file *filp, - i += sz - ret; - rb->cons += sz - ret; - -- if (ret != sz) { -+ if (ret != 0) { - if (i == 0) - i = -EFAULT; - goto out; -@@ -453,7 +453,7 @@ static ssize_t xenbus_file_write(struct file *filp, - - ret = copy_from_user(u->u.buffer + u->len, ubuf, len); - -- if (ret == len) { -+ if (ret != 0) { - rc = -EFAULT; - goto out; - } --- -1.7.3.4 - - -From 6d6df2e412297b8047c407b3abcd045a67c96744 Mon Sep 17 00:00:00 2001 -From: Diego Ongaro -Date: Wed, 1 Sep 2010 09:18:54 -0700 -Subject: [PATCH 02/43] xenbus: allow any xenbus command over /proc/xen/xenbus - -When xenstored is in another domain, we need to be able to send any -command over xenbus. This doesn't pose a security problem because -its up to xenstored to determine whether a given client is allowed -to use a particular command anyway. - -From linux-2.5.18-xen.hg 68d582b0ad05. - -Signed-off-by: Jeremy Fitzhardinge ---- - drivers/xen/xenfs/xenbus.c | 18 ++---------------- - 1 files changed, 2 insertions(+), 16 deletions(-) - -diff --git a/drivers/xen/xenfs/xenbus.c b/drivers/xen/xenfs/xenbus.c -index d2a9058..46cf404 100644 ---- a/drivers/xen/xenfs/xenbus.c -+++ b/drivers/xen/xenfs/xenbus.c -@@ -486,21 +486,6 @@ static ssize_t xenbus_file_write(struct file *filp, - msg_type = u->u.msg.type; - - switch (msg_type) { -- case XS_TRANSACTION_START: -- case XS_TRANSACTION_END: -- case XS_DIRECTORY: -- case XS_READ: -- case XS_GET_PERMS: -- case XS_RELEASE: -- case XS_GET_DOMAIN_PATH: -- case XS_WRITE: -- case XS_MKDIR: -- case XS_RM: -- case XS_SET_PERMS: -- /* Send out a transaction */ -- ret = xenbus_write_transaction(msg_type, u); -- break; -- - case XS_WATCH: - case XS_UNWATCH: - /* (Un)Ask for some path to be watched for changes */ -@@ -508,7 +493,8 @@ static ssize_t xenbus_file_write(struct file *filp, - break; - - default: -- ret = -EINVAL; -+ /* Send out a transaction */ -+ ret = xenbus_write_transaction(msg_type, u); - break; - } - if (ret != 0) --- -1.7.3.4 - - -From 76ce7618f9a24f7b13958c67f7d5ccfcdab71475 Mon Sep 17 00:00:00 2001 -From: Daniel De Graaf -Date: Tue, 7 Sep 2010 11:42:18 -0400 -Subject: [PATCH 03/43] xenbus: add missing wakeup in concurrent read/write - -If an application has a dedicated read thread watching xenbus and -another thread writes an XS_WATCH message that generates a synthetic -"OK" reply, this reply will be enqueued in the buffer without waking up -the reader. This can cause a deadlock in the application if it then -waits for the read thread to receive the queued message. - -Signed-off-by: Daniel De Graaf - -commit e752969f502a511e83f841aa01d6cd332e6d85a0 -Author: Daniel De Graaf -Date: Tue Sep 7 11:21:52 2010 -0400 - - xenbus: fix deadlock in concurrent read/write - - If an application has a dedicated read thread watching xenbus and another - thread writes an XS_WATCH message that generates a synthetic "OK" reply, - this reply will be enqueued in the buffer without waking up the reader. -Signed-off-by: Jeremy Fitzhardinge ---- - drivers/xen/xenfs/xenbus.c | 1 + - 1 files changed, 1 insertions(+), 0 deletions(-) - -diff --git a/drivers/xen/xenfs/xenbus.c b/drivers/xen/xenfs/xenbus.c -index 46cf404..c4c7db8 100644 ---- a/drivers/xen/xenfs/xenbus.c -+++ b/drivers/xen/xenfs/xenbus.c -@@ -405,6 +405,7 @@ static int xenbus_write_watch(unsigned msg_type, struct xenbus_file_priv *u) - - mutex_lock(&u->reply_mutex); - rc = queue_reply(&u->read_buffers, &reply, sizeof(reply)); -+ wake_up(&u->read_waitq); - mutex_unlock(&u->reply_mutex); - } - --- -1.7.3.4 - - -From 7808121b9a1e44ef12fecd49fa6c268f27a150fc Mon Sep 17 00:00:00 2001 -From: Daniel De Graaf -Date: Wed, 8 Sep 2010 18:10:42 -0400 -Subject: [PATCH 04/43] xenbus: avoid zero returns from read() - -It is possible to get a zero return from read() in instances where the -queue is not empty but has no elements with data to deliver to the user. -Since a zero return from read is an error indicator, resume waiting or -return -EAGAIN (for a nonblocking fd) in this case. - -Signed-off-by: Daniel De Graaf -Signed-off-by: Jeremy Fitzhardinge ---- - drivers/xen/xenfs/xenbus.c | 3 +++ - 1 files changed, 3 insertions(+), 0 deletions(-) - -diff --git a/drivers/xen/xenfs/xenbus.c b/drivers/xen/xenfs/xenbus.c -index c4c7db8..55791dd 100644 ---- a/drivers/xen/xenfs/xenbus.c -+++ b/drivers/xen/xenfs/xenbus.c -@@ -120,6 +120,7 @@ static ssize_t xenbus_file_read(struct file *filp, - int ret; - - mutex_lock(&u->reply_mutex); -+again: - while (list_empty(&u->read_buffers)) { - mutex_unlock(&u->reply_mutex); - if (filp->f_flags & O_NONBLOCK) -@@ -158,6 +159,8 @@ static ssize_t xenbus_file_read(struct file *filp, - struct read_buffer, list); - } - } -+ if (i == 0) -+ goto again; - - out: - mutex_unlock(&u->reply_mutex); --- -1.7.3.4 - - From 8bd6ddfd569309d8e915ffb6f68ad7bf03e53922 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Fri, 20 Feb 2009 12:58:42 -0800 @@ -1283,958 +1102,6 @@ index 235c0f4..4ad88fd 100644 1.7.3.4 -From a188301f0e78daed011dde56139630d88299a954 Mon Sep 17 00:00:00 2001 -From: Ian Campbell -Date: Mon, 9 Feb 2009 12:05:49 -0800 -Subject: [PATCH 17/43] xen: define gnttab_set_map_op/unmap_op - -Impact: hypercall definitions - -These functions populate the gnttab data structures used by the -granttab map and unmap ops and are used in the backend drivers. - -Originally xen-unstable.hg 9625:c3bb51c443a7 - -[ Include Stefano's fix for phys_addr_t ] - -Signed-off-by: Ian Campbell -Signed-off-by: Stefano Stabellini -Signed-off-by: Jeremy Fitzhardinge ---- - include/xen/grant_table.h | 39 ++++++++++++++++++++++++++++++++++++++- - 1 files changed, 38 insertions(+), 1 deletions(-) - -diff --git a/include/xen/grant_table.h b/include/xen/grant_table.h -index 9a73170..1821aa1 100644 ---- a/include/xen/grant_table.h -+++ b/include/xen/grant_table.h -@@ -37,10 +37,16 @@ - #ifndef __ASM_GNTTAB_H__ - #define __ASM_GNTTAB_H__ - --#include -+#include -+ -+#include - #include -+ -+#include - #include - -+#include -+ - /* NR_GRANT_FRAMES must be less than or equal to that configured in Xen */ - #define NR_GRANT_FRAMES 4 - -@@ -107,6 +113,37 @@ void gnttab_grant_foreign_access_ref(grant_ref_t ref, domid_t domid, - void gnttab_grant_foreign_transfer_ref(grant_ref_t, domid_t domid, - unsigned long pfn); - -+static inline void -+gnttab_set_map_op(struct gnttab_map_grant_ref *map, phys_addr_t addr, -+ uint32_t flags, grant_ref_t ref, domid_t domid) -+{ -+ if (flags & GNTMAP_contains_pte) -+ map->host_addr = addr; -+ else if (xen_feature(XENFEAT_auto_translated_physmap)) -+ map->host_addr = __pa(addr); -+ else -+ map->host_addr = addr; -+ -+ map->flags = flags; -+ map->ref = ref; -+ map->dom = domid; -+} -+ -+static inline void -+gnttab_set_unmap_op(struct gnttab_unmap_grant_ref *unmap, phys_addr_t addr, -+ uint32_t flags, grant_handle_t handle) -+{ -+ if (flags & GNTMAP_contains_pte) -+ unmap->host_addr = addr; -+ else if (xen_feature(XENFEAT_auto_translated_physmap)) -+ unmap->host_addr = __pa(addr); -+ else -+ unmap->host_addr = addr; -+ -+ unmap->handle = handle; -+ unmap->dev_bus_addr = 0; -+} -+ - int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes, - unsigned long max_nr_gframes, - struct grant_entry **__shared); --- -1.7.3.4 - - -From 56385560d6d8fd4c89c4f328d3ff0ecc9c44c52d Mon Sep 17 00:00:00 2001 -From: Gerd Hoffmann -Date: Tue, 3 Mar 2009 12:27:55 -0800 -Subject: [PATCH 18/43] xen/gntdev: allow usermode to map granted pages - -The gntdev driver allows usermode to map granted pages from other -domains. This is typically used to implement a Xen backend driver -in user mode. - -Signed-off-by: Gerd Hoffmann -Signed-off-by: Stefano Stabellini -Signed-off-by: Jeremy Fitzhardinge ---- - drivers/xen/Kconfig | 7 + - drivers/xen/Makefile | 4 + - drivers/xen/gntdev.c | 646 ++++++++++++++++++++++++++++++++++++++++++++++++++ - include/xen/gntdev.h | 119 +++++++++ - 4 files changed, 776 insertions(+), 0 deletions(-) - create mode 100644 drivers/xen/gntdev.c - create mode 100644 include/xen/gntdev.h - -diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig -index 6e6180c..0c6d2a1 100644 ---- a/drivers/xen/Kconfig -+++ b/drivers/xen/Kconfig -@@ -62,6 +62,13 @@ config XEN_SYS_HYPERVISOR - virtual environment, /sys/hypervisor will still be present, - but will have no xen contents. - -+config XEN_GNTDEV -+ tristate "userspace grant access device driver" -+ depends on XEN -+ select MMU_NOTIFIER -+ help -+ Allows userspace processes use grants. -+ - config XEN_PLATFORM_PCI - tristate "xen platform pci device driver" - depends on XEN_PVHVM -diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile -index eb8a78d..7ed8418 100644 ---- a/drivers/xen/Makefile -+++ b/drivers/xen/Makefile -@@ -9,6 +9,7 @@ obj-$(CONFIG_HOTPLUG_CPU) += cpu_hotplug.o - obj-$(CONFIG_XEN_XENCOMM) += xencomm.o - obj-$(CONFIG_XEN_BALLOON) += balloon.o - obj-$(CONFIG_XEN_DEV_EVTCHN) += xen-evtchn.o -+obj-$(CONFIG_XEN_GNTDEV) += xen-gntdev.o - obj-$(CONFIG_XENFS) += xenfs/ - obj-$(CONFIG_XEN_SYS_HYPERVISOR) += sys-hypervisor.o - obj-$(CONFIG_XEN_PLATFORM_PCI) += platform-pci.o -@@ -17,3 +18,5 @@ obj-$(CONFIG_HOTPLUG_CPU) += cpu_hotplug.o - - xen-evtchn-y := evtchn.o - -+xen-gntdev-y := gntdev.o -+ -diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c -new file mode 100644 -index 0000000..45898d4 ---- /dev/null -+++ b/drivers/xen/gntdev.c -@@ -0,0 +1,646 @@ -+/****************************************************************************** -+ * gntdev.c -+ * -+ * Device for accessing (in user-space) pages that have been granted by other -+ * domains. -+ * -+ * Copyright (c) 2006-2007, D G Murray. -+ * (c) 2009 Gerd Hoffmann -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Derek G. Murray , " -+ "Gerd Hoffmann "); -+MODULE_DESCRIPTION("User-space granted page access driver"); -+ -+static int debug = 0; -+module_param(debug, int, 0644); -+static int limit = 1024; -+module_param(limit, int, 0644); -+ -+struct gntdev_priv { -+ struct list_head maps; -+ uint32_t used; -+ uint32_t limit; -+ spinlock_t lock; -+ struct mm_struct *mm; -+ struct mmu_notifier mn; -+}; -+ -+struct grant_map { -+ struct list_head next; -+ struct gntdev_priv *priv; -+ struct vm_area_struct *vma; -+ int index; -+ int count; -+ int flags; -+ int is_mapped; -+ struct ioctl_gntdev_grant_ref *grants; -+ struct gnttab_map_grant_ref *map_ops; -+ struct gnttab_unmap_grant_ref *unmap_ops; -+}; -+ -+/* ------------------------------------------------------------------ */ -+ -+static void gntdev_print_maps(struct gntdev_priv *priv, -+ char *text, int text_index) -+{ -+ struct grant_map *map; -+ -+ printk("%s: maps list (priv %p, usage %d/%d)\n", -+ __FUNCTION__, priv, priv->used, priv->limit); -+ list_for_each_entry(map, &priv->maps, next) -+ printk(" index %2d, count %2d %s\n", -+ map->index, map->count, -+ map->index == text_index && text ? text : ""); -+} -+ -+static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count) -+{ -+ struct grant_map *add; -+ -+ add = kzalloc(sizeof(struct grant_map), GFP_KERNEL); -+ if (NULL == add) -+ return NULL; -+ -+ add->grants = kzalloc(sizeof(add->grants[0]) * count, GFP_KERNEL); -+ add->map_ops = kzalloc(sizeof(add->map_ops[0]) * count, GFP_KERNEL); -+ add->unmap_ops = kzalloc(sizeof(add->unmap_ops[0]) * count, GFP_KERNEL); -+ if (NULL == add->grants || -+ NULL == add->map_ops || -+ NULL == add->unmap_ops) -+ goto err; -+ -+ add->index = 0; -+ add->count = count; -+ add->priv = priv; -+ -+ if (add->count + priv->used > priv->limit) -+ goto err; -+ -+ return add; -+ -+err: -+ kfree(add->grants); -+ kfree(add->map_ops); -+ kfree(add->unmap_ops); -+ kfree(add); -+ return NULL; -+} -+ -+static void gntdev_add_map(struct gntdev_priv *priv, struct grant_map *add) -+{ -+ struct grant_map *map; -+ -+ list_for_each_entry(map, &priv->maps, next) { -+ if (add->index + add->count < map->index) { -+ list_add_tail(&add->next, &map->next); -+ goto done; -+ } -+ add->index = map->index + map->count; -+ } -+ list_add_tail(&add->next, &priv->maps); -+ -+done: -+ priv->used += add->count; -+ if (debug) -+ gntdev_print_maps(priv, "[new]", add->index); -+} -+ -+static struct grant_map *gntdev_find_map_index(struct gntdev_priv *priv, int index, -+ int count) -+{ -+ struct grant_map *map; -+ -+ list_for_each_entry(map, &priv->maps, next) { -+ if (map->index != index) -+ continue; -+ if (map->count != count) -+ continue; -+ return map; -+ } -+ return NULL; -+} -+ -+static struct grant_map *gntdev_find_map_vaddr(struct gntdev_priv *priv, -+ unsigned long vaddr) -+{ -+ struct grant_map *map; -+ -+ list_for_each_entry(map, &priv->maps, next) { -+ if (!map->vma) -+ continue; -+ if (vaddr < map->vma->vm_start) -+ continue; -+ if (vaddr >= map->vma->vm_end) -+ continue; -+ return map; -+ } -+ return NULL; -+} -+ -+static int gntdev_del_map(struct grant_map *map) -+{ -+ int i; -+ -+ if (map->vma) -+ return -EBUSY; -+ for (i = 0; i < map->count; i++) -+ if (map->unmap_ops[i].handle) -+ return -EBUSY; -+ -+ map->priv->used -= map->count; -+ list_del(&map->next); -+ return 0; -+} -+ -+static void gntdev_free_map(struct grant_map *map) -+{ -+ if (!map) -+ return; -+ kfree(map->grants); -+ kfree(map->map_ops); -+ kfree(map->unmap_ops); -+ kfree(map); -+} -+ -+/* ------------------------------------------------------------------ */ -+ -+static int find_grant_ptes(pte_t *pte, pgtable_t token, unsigned long addr, void *data) -+{ -+ struct grant_map *map = data; -+ unsigned int pgnr = (addr - map->vma->vm_start) >> PAGE_SHIFT; -+ u64 pte_maddr; -+ -+ BUG_ON(pgnr >= map->count); -+ pte_maddr = (u64)pfn_to_mfn(page_to_pfn(token)) << PAGE_SHIFT; -+ pte_maddr += (unsigned long)pte & ~PAGE_MASK; -+ gnttab_set_map_op(&map->map_ops[pgnr], pte_maddr, map->flags, -+ map->grants[pgnr].ref, -+ map->grants[pgnr].domid); -+ gnttab_set_unmap_op(&map->unmap_ops[pgnr], pte_maddr, map->flags, -+ 0 /* handle */); -+ return 0; -+} -+ -+static int map_grant_pages(struct grant_map *map) -+{ -+ int i, err = 0; -+ -+ if (debug) -+ printk("%s: map %d+%d\n", __FUNCTION__, map->index, map->count); -+ err = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, -+ map->map_ops, map->count); -+ if (WARN_ON(err)) -+ return err; -+ -+ for (i = 0; i < map->count; i++) { -+ if (map->map_ops[i].status) -+ err = -EINVAL; -+ map->unmap_ops[i].handle = map->map_ops[i].handle; -+ } -+ return err; -+} -+ -+static int unmap_grant_pages(struct grant_map *map, int offset, int pages) -+{ -+ int i, err = 0; -+ -+ if (debug) -+ printk("%s: map %d+%d [%d+%d]\n", __FUNCTION__, -+ map->index, map->count, offset, pages); -+ err = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, -+ map->unmap_ops + offset, pages); -+ if (WARN_ON(err)) -+ return err; -+ -+ for (i = 0; i < pages; i++) { -+ if (map->unmap_ops[offset+i].status) -+ err = -EINVAL; -+ map->unmap_ops[offset+i].handle = 0; -+ } -+ return err; -+} -+ -+/* ------------------------------------------------------------------ */ -+ -+static void gntdev_vma_close(struct vm_area_struct *vma) -+{ -+ struct grant_map *map = vma->vm_private_data; -+ -+ if (debug) -+ printk("%s\n", __FUNCTION__); -+ map->is_mapped = 0; -+ map->vma = NULL; -+ vma->vm_private_data = NULL; -+} -+ -+static int gntdev_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf) -+{ -+ if (debug) -+ printk("%s: vaddr %p, pgoff %ld (shouldn't happen)\n", -+ __FUNCTION__, vmf->virtual_address, vmf->pgoff); -+ vmf->flags = VM_FAULT_ERROR; -+ return 0; -+} -+ -+static struct vm_operations_struct gntdev_vmops = { -+ .close = gntdev_vma_close, -+ .fault = gntdev_vma_fault, -+}; -+ -+/* ------------------------------------------------------------------ */ -+ -+static void mn_invl_range_start(struct mmu_notifier *mn, -+ struct mm_struct *mm, -+ unsigned long start, unsigned long end) -+{ -+ struct gntdev_priv *priv = container_of(mn, struct gntdev_priv, mn); -+ struct grant_map *map; -+ unsigned long mstart, mend; -+ int err; -+ -+ spin_lock(&priv->lock); -+ list_for_each_entry(map, &priv->maps, next) { -+ if (!map->vma) -+ continue; -+ if (!map->is_mapped) -+ continue; -+ if (map->vma->vm_start >= end) -+ continue; -+ if (map->vma->vm_end <= start) -+ continue; -+ mstart = max(start, map->vma->vm_start); -+ mend = min(end, map->vma->vm_end); -+ if (debug) -+ printk("%s: map %d+%d (%lx %lx), range %lx %lx, mrange %lx %lx\n", -+ __FUNCTION__, map->index, map->count, -+ map->vma->vm_start, map->vma->vm_end, -+ start, end, mstart, mend); -+ err = unmap_grant_pages(map, -+ (mstart - map->vma->vm_start) >> PAGE_SHIFT, -+ (mend - mstart) >> PAGE_SHIFT); -+ WARN_ON(err); -+ } -+ spin_unlock(&priv->lock); -+} -+ -+static void mn_invl_page(struct mmu_notifier *mn, -+ struct mm_struct *mm, -+ unsigned long address) -+{ -+ mn_invl_range_start(mn, mm, address, address + PAGE_SIZE); -+} -+ -+static void mn_release(struct mmu_notifier *mn, -+ struct mm_struct *mm) -+{ -+ struct gntdev_priv *priv = container_of(mn, struct gntdev_priv, mn); -+ struct grant_map *map; -+ int err; -+ -+ spin_lock(&priv->lock); -+ list_for_each_entry(map, &priv->maps, next) { -+ if (!map->vma) -+ continue; -+ if (debug) -+ printk("%s: map %d+%d (%lx %lx)\n", -+ __FUNCTION__, map->index, map->count, -+ map->vma->vm_start, map->vma->vm_end); -+ err = unmap_grant_pages(map, 0, map->count); -+ WARN_ON(err); -+ } -+ spin_unlock(&priv->lock); -+} -+ -+struct mmu_notifier_ops gntdev_mmu_ops = { -+ .release = mn_release, -+ .invalidate_page = mn_invl_page, -+ .invalidate_range_start = mn_invl_range_start, -+}; -+ -+/* ------------------------------------------------------------------ */ -+ -+static int gntdev_open(struct inode *inode, struct file *flip) -+{ -+ struct gntdev_priv *priv; -+ -+ priv = kzalloc(sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ -+ INIT_LIST_HEAD(&priv->maps); -+ spin_lock_init(&priv->lock); -+ priv->limit = limit; -+ -+ priv->mm = get_task_mm(current); -+ if (!priv->mm) { -+ kfree(priv); -+ return -ENOMEM; -+ } -+ priv->mn.ops = &gntdev_mmu_ops; -+ mmu_notifier_register(&priv->mn, priv->mm); -+ mmput(priv->mm); -+ -+ flip->private_data = priv; -+ if (debug) -+ printk("%s: priv %p\n", __FUNCTION__, priv); -+ -+ return 0; -+} -+ -+static int gntdev_release(struct inode *inode, struct file *flip) -+{ -+ struct gntdev_priv *priv = flip->private_data; -+ struct grant_map *map; -+ int err; -+ -+ if (debug) -+ printk("%s: priv %p\n", __FUNCTION__, priv); -+ -+ spin_lock(&priv->lock); -+ while (!list_empty(&priv->maps)) { -+ map = list_entry(priv->maps.next, struct grant_map, next); -+ err = gntdev_del_map(map); -+ if (WARN_ON(err)) -+ gntdev_free_map(map); -+ -+ } -+ spin_unlock(&priv->lock); -+ -+ mmu_notifier_unregister(&priv->mn, priv->mm); -+ kfree(priv); -+ return 0; -+} -+ -+static long gntdev_ioctl_map_grant_ref(struct gntdev_priv *priv, -+ struct ioctl_gntdev_map_grant_ref __user *u) -+{ -+ struct ioctl_gntdev_map_grant_ref op; -+ struct grant_map *map; -+ int err; -+ -+ if (copy_from_user(&op, u, sizeof(op)) != 0) -+ return -EFAULT; -+ if (debug) -+ printk("%s: priv %p, add %d\n", __FUNCTION__, priv, -+ op.count); -+ if (unlikely(op.count <= 0)) -+ return -EINVAL; -+ if (unlikely(op.count > priv->limit)) -+ return -EINVAL; -+ -+ err = -ENOMEM; -+ map = gntdev_alloc_map(priv, op.count); -+ if (!map) -+ return err; -+ if (copy_from_user(map->grants, &u->refs, -+ sizeof(map->grants[0]) * op.count) != 0) { -+ gntdev_free_map(map); -+ return err; -+ } -+ -+ spin_lock(&priv->lock); -+ gntdev_add_map(priv, map); -+ op.index = map->index << PAGE_SHIFT; -+ spin_unlock(&priv->lock); -+ -+ if (copy_to_user(u, &op, sizeof(op)) != 0) { -+ spin_lock(&priv->lock); -+ gntdev_del_map(map); -+ spin_unlock(&priv->lock); -+ gntdev_free_map(map); -+ return err; -+ } -+ return 0; -+} -+ -+static long gntdev_ioctl_unmap_grant_ref(struct gntdev_priv *priv, -+ struct ioctl_gntdev_unmap_grant_ref __user *u) -+{ -+ struct ioctl_gntdev_unmap_grant_ref op; -+ struct grant_map *map; -+ int err = -EINVAL; -+ -+ if (copy_from_user(&op, u, sizeof(op)) != 0) -+ return -EFAULT; -+ if (debug) -+ printk("%s: priv %p, del %d+%d\n", __FUNCTION__, priv, -+ (int)op.index, (int)op.count); -+ -+ spin_lock(&priv->lock); -+ map = gntdev_find_map_index(priv, op.index >> PAGE_SHIFT, op.count); -+ if (map) -+ err = gntdev_del_map(map); -+ spin_unlock(&priv->lock); -+ if (!err) -+ gntdev_free_map(map); -+ return err; -+} -+ -+static long gntdev_ioctl_get_offset_for_vaddr(struct gntdev_priv *priv, -+ struct ioctl_gntdev_get_offset_for_vaddr __user *u) -+{ -+ struct ioctl_gntdev_get_offset_for_vaddr op; -+ struct grant_map *map; -+ -+ if (copy_from_user(&op, u, sizeof(op)) != 0) -+ return -EFAULT; -+ if (debug) -+ printk("%s: priv %p, offset for vaddr %lx\n", __FUNCTION__, priv, -+ (unsigned long)op.vaddr); -+ -+ spin_lock(&priv->lock); -+ map = gntdev_find_map_vaddr(priv, op.vaddr); -+ if (map == NULL || -+ map->vma->vm_start != op.vaddr) { -+ spin_unlock(&priv->lock); -+ return -EINVAL; -+ } -+ op.offset = map->index << PAGE_SHIFT; -+ op.count = map->count; -+ spin_unlock(&priv->lock); -+ -+ if (copy_to_user(u, &op, sizeof(op)) != 0) -+ return -EFAULT; -+ return 0; -+} -+ -+static long gntdev_ioctl_set_max_grants(struct gntdev_priv *priv, -+ struct ioctl_gntdev_set_max_grants __user *u) -+{ -+ struct ioctl_gntdev_set_max_grants op; -+ -+ if (copy_from_user(&op, u, sizeof(op)) != 0) -+ return -EFAULT; -+ if (debug) -+ printk("%s: priv %p, limit %d\n", __FUNCTION__, priv, op.count); -+ if (op.count > limit) -+ return -EINVAL; -+ -+ spin_lock(&priv->lock); -+ priv->limit = op.count; -+ spin_unlock(&priv->lock); -+ return 0; -+} -+ -+static long gntdev_ioctl(struct file *flip, -+ unsigned int cmd, unsigned long arg) -+{ -+ struct gntdev_priv *priv = flip->private_data; -+ void __user *ptr = (void __user *)arg; -+ -+ switch (cmd) { -+ case IOCTL_GNTDEV_MAP_GRANT_REF: -+ return gntdev_ioctl_map_grant_ref(priv, ptr); -+ -+ case IOCTL_GNTDEV_UNMAP_GRANT_REF: -+ return gntdev_ioctl_unmap_grant_ref(priv, ptr); -+ -+ case IOCTL_GNTDEV_GET_OFFSET_FOR_VADDR: -+ return gntdev_ioctl_get_offset_for_vaddr(priv, ptr); -+ -+ case IOCTL_GNTDEV_SET_MAX_GRANTS: -+ return gntdev_ioctl_set_max_grants(priv, ptr); -+ -+ default: -+ if (debug) -+ printk("%s: priv %p, unknown cmd %x\n", -+ __FUNCTION__, priv, cmd); -+ return -ENOIOCTLCMD; -+ } -+ -+ return 0; -+} -+ -+static int gntdev_mmap(struct file *flip, struct vm_area_struct *vma) -+{ -+ struct gntdev_priv *priv = flip->private_data; -+ int index = vma->vm_pgoff; -+ int count = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; -+ struct grant_map *map; -+ int err = -EINVAL; -+ -+ if ((vma->vm_flags & VM_WRITE) && !(vma->vm_flags & VM_SHARED)) -+ return -EINVAL; -+ -+ if (debug) -+ printk("%s: map %d+%d at %lx (pgoff %lx)\n", __FUNCTION__, -+ index, count, vma->vm_start, vma->vm_pgoff); -+ -+ spin_lock(&priv->lock); -+ map = gntdev_find_map_index(priv, index, count); -+ if (!map) -+ goto unlock_out; -+ if (map->vma) -+ goto unlock_out; -+ if (priv->mm != vma->vm_mm) { -+ printk("%s: Huh? Other mm?\n", __FUNCTION__); -+ goto unlock_out; -+ } -+ -+ vma->vm_ops = &gntdev_vmops; -+ -+ vma->vm_flags |= VM_RESERVED; -+ vma->vm_flags |= VM_DONTCOPY; -+ vma->vm_flags |= VM_DONTEXPAND; -+ -+ vma->vm_private_data = map; -+ map->vma = vma; -+ -+ map->flags = GNTMAP_host_map | GNTMAP_application_map | GNTMAP_contains_pte; -+ if (!(vma->vm_flags & VM_WRITE)) -+ map->flags |= GNTMAP_readonly; -+ -+ err = apply_to_page_range(vma->vm_mm, vma->vm_start, -+ vma->vm_end - vma->vm_start, -+ find_grant_ptes, map); -+ if (err) { -+ goto unlock_out; -+ if (debug) -+ printk("%s: find_grant_ptes() failure.\n", __FUNCTION__); -+ } -+ -+ err = map_grant_pages(map); -+ if (err) { -+ goto unlock_out; -+ if (debug) -+ printk("%s: map_grant_pages() failure.\n", __FUNCTION__); -+ } -+ map->is_mapped = 1; -+ -+unlock_out: -+ spin_unlock(&priv->lock); -+ return err; -+} -+ -+static const struct file_operations gntdev_fops = { -+ .owner = THIS_MODULE, -+ .open = gntdev_open, -+ .release = gntdev_release, -+ .mmap = gntdev_mmap, -+ .unlocked_ioctl = gntdev_ioctl -+}; -+ -+static struct miscdevice gntdev_miscdev = { -+ .minor = MISC_DYNAMIC_MINOR, -+ .name = "xen/gntdev", -+ .fops = &gntdev_fops, -+}; -+ -+/* ------------------------------------------------------------------ */ -+ -+static int __init gntdev_init(void) -+{ -+ int err; -+ -+ if (!xen_domain()) -+ return -ENODEV; -+ -+ err = misc_register(&gntdev_miscdev); -+ if (err != 0) { -+ printk(KERN_ERR "Could not register gntdev device\n"); -+ return err; -+ } -+ return 0; -+} -+ -+static void __exit gntdev_exit(void) -+{ -+ misc_deregister(&gntdev_miscdev); -+} -+ -+module_init(gntdev_init); -+module_exit(gntdev_exit); -+ -+/* ------------------------------------------------------------------ */ -diff --git a/include/xen/gntdev.h b/include/xen/gntdev.h -new file mode 100644 -index 0000000..8bd1467 ---- /dev/null -+++ b/include/xen/gntdev.h -@@ -0,0 +1,119 @@ -+/****************************************************************************** -+ * gntdev.h -+ * -+ * Interface to /dev/xen/gntdev. -+ * -+ * Copyright (c) 2007, D G Murray -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License version 2 -+ * as published by the Free Software Foundation; or, when distributed -+ * separately from the Linux kernel or incorporated into other -+ * software packages, subject to the following license: -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a copy -+ * of this source file (the "Software"), to deal in the Software without -+ * restriction, including without limitation the rights to use, copy, modify, -+ * merge, publish, distribute, sublicense, and/or sell copies of the Software, -+ * and to permit persons to whom the Software is furnished to do so, subject to -+ * the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -+ * IN THE SOFTWARE. -+ */ -+ -+#ifndef __LINUX_PUBLIC_GNTDEV_H__ -+#define __LINUX_PUBLIC_GNTDEV_H__ -+ -+struct ioctl_gntdev_grant_ref { -+ /* The domain ID of the grant to be mapped. */ -+ uint32_t domid; -+ /* The grant reference of the grant to be mapped. */ -+ uint32_t ref; -+}; -+ -+/* -+ * Inserts the grant references into the mapping table of an instance -+ * of gntdev. N.B. This does not perform the mapping, which is deferred -+ * until mmap() is called with @index as the offset. -+ */ -+#define IOCTL_GNTDEV_MAP_GRANT_REF \ -+_IOC(_IOC_NONE, 'G', 0, sizeof(struct ioctl_gntdev_map_grant_ref)) -+struct ioctl_gntdev_map_grant_ref { -+ /* IN parameters */ -+ /* The number of grants to be mapped. */ -+ uint32_t count; -+ uint32_t pad; -+ /* OUT parameters */ -+ /* The offset to be used on a subsequent call to mmap(). */ -+ uint64_t index; -+ /* Variable IN parameter. */ -+ /* Array of grant references, of size @count. */ -+ struct ioctl_gntdev_grant_ref refs[1]; -+}; -+ -+/* -+ * Removes the grant references from the mapping table of an instance of -+ * of gntdev. N.B. munmap() must be called on the relevant virtual address(es) -+ * before this ioctl is called, or an error will result. -+ */ -+#define IOCTL_GNTDEV_UNMAP_GRANT_REF \ -+_IOC(_IOC_NONE, 'G', 1, sizeof(struct ioctl_gntdev_unmap_grant_ref)) -+struct ioctl_gntdev_unmap_grant_ref { -+ /* IN parameters */ -+ /* The offset was returned by the corresponding map operation. */ -+ uint64_t index; -+ /* The number of pages to be unmapped. */ -+ uint32_t count; -+ uint32_t pad; -+}; -+ -+/* -+ * Returns the offset in the driver's address space that corresponds -+ * to @vaddr. This can be used to perform a munmap(), followed by an -+ * UNMAP_GRANT_REF ioctl, where no state about the offset is retained by -+ * the caller. The number of pages that were allocated at the same time as -+ * @vaddr is returned in @count. -+ * -+ * N.B. Where more than one page has been mapped into a contiguous range, the -+ * supplied @vaddr must correspond to the start of the range; otherwise -+ * an error will result. It is only possible to munmap() the entire -+ * contiguously-allocated range at once, and not any subrange thereof. -+ */ -+#define IOCTL_GNTDEV_GET_OFFSET_FOR_VADDR \ -+_IOC(_IOC_NONE, 'G', 2, sizeof(struct ioctl_gntdev_get_offset_for_vaddr)) -+struct ioctl_gntdev_get_offset_for_vaddr { -+ /* IN parameters */ -+ /* The virtual address of the first mapped page in a range. */ -+ uint64_t vaddr; -+ /* OUT parameters */ -+ /* The offset that was used in the initial mmap() operation. */ -+ uint64_t offset; -+ /* The number of pages mapped in the VM area that begins at @vaddr. */ -+ uint32_t count; -+ uint32_t pad; -+}; -+ -+/* -+ * Sets the maximum number of grants that may mapped at once by this gntdev -+ * instance. -+ * -+ * N.B. This must be called before any other ioctl is performed on the device. -+ */ -+#define IOCTL_GNTDEV_SET_MAX_GRANTS \ -+_IOC(_IOC_NONE, 'G', 3, sizeof(struct ioctl_gntdev_set_max_grants)) -+struct ioctl_gntdev_set_max_grants { -+ /* IN parameter */ -+ /* The maximum number of grants that may be mapped at once. */ -+ uint32_t count; -+}; -+ -+#endif /* __LINUX_PUBLIC_GNTDEV_H__ */ --- -1.7.3.4 - - -From 8c79aad3bd8a379bd0bd144895b55098aca2ccea Mon Sep 17 00:00:00 2001 -From: Jeremy Fitzhardinge -Date: Thu, 11 Nov 2010 14:39:12 -0800 -Subject: [PATCH 19/43] xen/gntdev: add VM_PFNMAP to vma - -These pages are from other domains, so don't have any local PFN. -VM_PFNMAP is the closest concept Linux has to this. - -Signed-off-by: Jeremy Fitzhardinge ---- - drivers/xen/gntdev.c | 1 + - 1 files changed, 1 insertions(+), 0 deletions(-) - -diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c -index 45898d4..cf61c7d 100644 ---- a/drivers/xen/gntdev.c -+++ b/drivers/xen/gntdev.c -@@ -574,6 +574,7 @@ static int gntdev_mmap(struct file *flip, struct vm_area_struct *vma) - vma->vm_flags |= VM_RESERVED; - vma->vm_flags |= VM_DONTCOPY; - vma->vm_flags |= VM_DONTEXPAND; -+ vma->vm_flags |= VM_PFNMAP; - - vma->vm_private_data = map; - map->vma = vma; --- -1.7.3.4 - - From 66b66fdaae7856319170b10f4690f67cf6129825 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Tue, 30 Nov 2010 10:03:44 -0800 @@ -3131,48 +1998,6 @@ index 49ba9b5..9cdb35e 100644 1.7.3.4 -From fefbfcc5c7f9c24ec98545254d8972f0faad0c44 Mon Sep 17 00:00:00 2001 -From: Ian Campbell -Date: Fri, 3 Dec 2010 09:54:03 +0000 -Subject: [PATCH 40/43] xen: disable ACPI NUMA for PV guests - -Xen does not currently expose PV-NUMA information to PV -guests. Therefore disable NUMA for the time being to prevent the -kernel picking up on an host-level NUMA information which it might -come across in the firmware. - -[ Added comment - Jeremy ] - -Signed-off-by: Ian Campbell -Signed-off-by: Jeremy Fitzhardinge ---- - arch/x86/xen/enlighten.c | 9 +++++++++ - 1 files changed, 9 insertions(+), 0 deletions(-) - -diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c -index 7250bef..33a7a83 100644 ---- a/arch/x86/xen/enlighten.c -+++ b/arch/x86/xen/enlighten.c -@@ -1178,6 +1178,15 @@ asmlinkage void __init xen_start_kernel(void) - - xen_smp_init(); - -+#ifdef CONFIG_ACPI_NUMA -+ /* -+ * The pages we from Xen are not related to machine pages, so -+ * any NUMA information the kernel tries to get from ACPI will -+ * be meaningless. Prevent it from trying. -+ */ -+ acpi_numa = -1; -+#endif -+ - pgd = (pgd_t *)xen_start_info->pt_base; - - if (!xen_initial_domain()) --- -1.7.3.4 - - From ac527c664a6f52fd780fd324deb0b018d4a4a357 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Wed, 3 Nov 2010 16:40:48 -0400 @@ -3238,43 +2063,3 @@ index 8760cc6..05c5cf5 100644 1.7.3.4 -From 6a5b3beff916a19e7672f8c0330b4f82ed367be2 Mon Sep 17 00:00:00 2001 -From: Daniel De Graaf -Date: Mon, 20 Dec 2010 14:56:09 -0800 -Subject: [PATCH 43/43] xenbus: Fix memory leak on release - -Pending responses were leaked on close. - -Signed-off-by: Daniel De Graaf -Signed-off-by: Jan Beulich -Signed-off-by: Jeremy Fitzhardinge ---- - drivers/xen/xenfs/xenbus.c | 5 +++++ - 1 files changed, 5 insertions(+), 0 deletions(-) - -diff --git a/drivers/xen/xenfs/xenbus.c b/drivers/xen/xenfs/xenbus.c -index 55791dd..8f6c7d4 100644 ---- a/drivers/xen/xenfs/xenbus.c -+++ b/drivers/xen/xenfs/xenbus.c -@@ -543,6 +543,7 @@ static int xenbus_file_release(struct inode *inode, struct file *filp) - struct xenbus_file_priv *u = filp->private_data; - struct xenbus_transaction_holder *trans, *tmp; - struct watch_adapter *watch, *tmp_watch; -+ struct read_buffer *rb, *tmp_rb; - - /* - * No need for locking here because there are no other users, -@@ -561,6 +562,10 @@ static int xenbus_file_release(struct inode *inode, struct file *filp) - free_watch_adapter(watch); - } - -+ list_for_each_entry_safe(rb, tmp_rb, &u->read_buffers, list) { -+ list_del(&rb->list); -+ kfree(rb); -+ } - kfree(u); - - return 0; --- -1.7.3.4 - diff --git a/xen.pcifront.fixes.patch b/xen.pcifront.fixes.patch index fff6708..c69852f 100644 --- a/xen.pcifront.fixes.patch +++ b/xen.pcifront.fixes.patch @@ -1,63 +1,3 @@ -From d1b758ebc2a82d738092cb42e742470f9d0ea53e Mon Sep 17 00:00:00 2001 -From: Konrad Rzeszutek Wilk -Date: Thu, 9 Dec 2010 14:53:29 -0500 -Subject: [PATCH 1/6] xen/irq: Cleanup the find_unbound_irq - -The "find_unbound_irq" is a bit unusual - it allocates -virtual IRQ (event channels) in reverse order. This means -starting at the "top" of the available IRQs (nr_irqs) down -to the GSI/MSI IRQs (nr_irqs_gsi). Lets document this and -also make the variables easier to understand. - -Signed-off-by: Konrad Rzeszutek Wilk ---- - drivers/xen/events.c | 18 ++++++++++++------ - 1 files changed, 12 insertions(+), 6 deletions(-) - -diff --git a/drivers/xen/events.c b/drivers/xen/events.c -index 31af0ac..4d4a23d 100644 ---- a/drivers/xen/events.c -+++ b/drivers/xen/events.c -@@ -405,15 +405,21 @@ static int find_unbound_irq(void) - { - struct irq_data *data; - int irq, res; -- int start = get_nr_hw_irqs(); -+ int bottom = get_nr_hw_irqs(); -+ int top = nr_irqs-1; - -- if (start == nr_irqs) -+ if (bottom == nr_irqs) - goto no_irqs; - -- /* nr_irqs is a magic value. Must not use it.*/ -- for (irq = nr_irqs-1; irq > start; irq--) { -+ /* This loop starts from the top of IRQ space and goes down. -+ * We need this b/c if we have a PCI device in a Xen PV guest -+ * we do not have an IO-APIC (though the backend might have them) -+ * mapped in. To not have a collision of physical IRQs with the Xen -+ * event channels start at the top of the IRQ space for virtual IRQs. -+ */ -+ for (irq = top; irq > bottom; irq--) { - data = irq_get_irq_data(irq); -- /* only 0->15 have init'd desc; handle irq > 16 */ -+ /* only 15->0 have init'd desc; handle irq > 16 */ - if (!data) - break; - if (data->chip == &no_irq_chip) -@@ -424,7 +430,7 @@ static int find_unbound_irq(void) - return irq; - } - -- if (irq == start) -+ if (irq == bottom) - goto no_irqs; - - res = irq_alloc_desc_at(irq, -1); --- -1.7.3.4 - - From 25c95c6ab7b9e257a60ac3eac73fa1acb120c692 Mon Sep 17 00:00:00 2001 From: Kenji Wakamiya Date: Tue, 14 Dec 2010 14:31:36 +0900 @@ -95,409 +35,6 @@ index db8c4c4..e32b9c0 100644 1.7.3.4 -From b225ec7d9bd6009b9885b7359b86fe6f46f4ae4c Mon Sep 17 00:00:00 2001 -From: Joe Jin -Date: Fri, 7 Jan 2011 18:17:17 +0800 -Subject: [PATCH 4/6] xen/fb: fix xenfb suspend/resume race. - -When migrating guests over a long period we hit this: - -<1>BUG: unable to handle kernel paging request at 0000000b819fdb98 -<1>IP: [] notify_remote_via_irq+0x13/0x34 -<4>PGD 94b10067 PUD 0 -<0>Oops: 0000 [#1] SMP -.. snip.. -Call Trace: - [] xenfb_send_event+0x5c/0x5e - [] ? xen_restore_fl_direct_end+0x0/0x1 - [] ? _spin_unlock_irqrestore+0x16/0x18 - [] xenfb_refresh+0x1b1/0x1d7 - [] ? sys_imageblit+0x1ac/0x458 - [] xenfb_imageblit+0x2f/0x34 - [] soft_cursor+0x1b5/0x1c8 - [] bit_cursor+0x4b6/0x4d7 - [] ? xen_restore_fl_direct_end+0x0/0x1 - [] ? _spin_unlock_irqrestore+0x16/0x18 - [] ? bit_cursor+0x0/0x4d7 - [] fb_flashcursor+0xff/0x111 - [] ? fb_flashcursor+0x0/0x111 - [] worker_thread+0x14d/0x1ed - [] ? autoremove_wake_function+0x0/0x3d - [] ? _spin_unlock_irqrestore+0x16/0x18 - [] ? worker_thread+0x0/0x1ed - [] kthread+0x6e/0x76 - [] child_rip+0xa/0x20 - [] ? int_ret_from_sys_call+0x7/0x1b - [] ? retint_restore_args+0x5/0x6 - [] ? child_rip+0x0/0x20 -Code: 6b ff 0c 8b 87 a4 db 9f 81 66 85 c0 74 08 0f b7 f8 e8 3b ff ff ff c9 -c3 55 48 89 e5 48 83 ec 10 0f 1f 44 00 00 89 ff 48 6b ff 0c <8b> 87 a4 db 9f -81 66 85 c0 74 14 48 8d 75 f0 0f b7 c0 bf 04 00 -RIP [] notify_remote_via_irq+0x13/0x34 - RSP -CR2: 0000000b819fdb98 ----[ end trace 098b4b74827595d0 ]--- - -The root cause of the panic is the race between the resume and reconnect to the backend. - -Clearing the 'update_wanted' flag of xenfb before disconnecting from the -backend fixes this issue. - -Signed-off-by: Joe Jin -Signed-off-by: Konrad Rzeszutek Wilk -Tested-by: Gurudas Pai -Acked-by: Ian Campbell -Cc: Jeremy Fitzhardinge -Cc: Andrew Morton ---- - drivers/video/xen-fbfront.c | 2 ++ - 1 files changed, 2 insertions(+), 0 deletions(-) - -diff --git a/drivers/video/xen-fbfront.c b/drivers/video/xen-fbfront.c -index 428d273..f92313d 100644 ---- a/drivers/video/xen-fbfront.c -+++ b/drivers/video/xen-fbfront.c -@@ -617,6 +617,8 @@ static int xenfb_connect_backend(struct xenbus_device *dev, - - static void xenfb_disconnect_backend(struct xenfb_info *info) - { -+ /* Prevent xenfb refresh */ -+ info->update_wanted = 0; - if (info->irq >= 0) - unbind_from_irqhandler(info->irq, info); - info->irq = -1; --- -1.7.3.4 - - -From c837d281ea3bcba81f7cef24bc6d6037be121f02 Mon Sep 17 00:00:00 2001 -From: Joe Jin -Date: Fri, 7 Jan 2011 18:20:54 +0800 -Subject: [PATCH 5/6] xen/fb: fix potential memory leak - -This patch fixes a potential memory leak when xenfb connect to -the backend fails. - -Thanks for Ian's review and comments. - -[v2: reworded the commit message a bit] - -Signed-off-by: Konrad Rzeszutek Wilk -Signed-off-by: Joe Jin -Tested-by: Gurudas Pai -Acked-by: Ian Campbell -Cc: Jeremy Fitzhardinge -Cc: Andrew Morton ---- - drivers/video/xen-fbfront.c | 17 +++++++++-------- - 1 files changed, 9 insertions(+), 8 deletions(-) - -diff --git a/drivers/video/xen-fbfront.c b/drivers/video/xen-fbfront.c -index f92313d..95bbd0a 100644 ---- a/drivers/video/xen-fbfront.c -+++ b/drivers/video/xen-fbfront.c -@@ -562,26 +562,24 @@ static void xenfb_init_shared_page(struct xenfb_info *info, - static int xenfb_connect_backend(struct xenbus_device *dev, - struct xenfb_info *info) - { -- int ret, evtchn; -+ int ret, evtchn, irq; - struct xenbus_transaction xbt; - - ret = xenbus_alloc_evtchn(dev, &evtchn); - if (ret) - return ret; -- ret = bind_evtchn_to_irqhandler(evtchn, xenfb_event_handler, -+ irq = bind_evtchn_to_irqhandler(evtchn, xenfb_event_handler, - 0, dev->devicetype, info); -- if (ret < 0) { -+ if (irq < 0) { - xenbus_free_evtchn(dev, evtchn); - xenbus_dev_fatal(dev, ret, "bind_evtchn_to_irqhandler"); -- return ret; -+ return irq; - } -- info->irq = ret; -- - again: - ret = xenbus_transaction_start(&xbt); - if (ret) { - xenbus_dev_fatal(dev, ret, "starting transaction"); -- return ret; -+ goto unbind_irq; - } - ret = xenbus_printf(xbt, dev->nodename, "page-ref", "%lu", - virt_to_mfn(info->page)); -@@ -603,15 +601,18 @@ static int xenfb_connect_backend(struct xenbus_device *dev, - if (ret == -EAGAIN) - goto again; - xenbus_dev_fatal(dev, ret, "completing transaction"); -- return ret; -+ goto unbind_irq; - } - - xenbus_switch_state(dev, XenbusStateInitialised); -+ info->irq = irq; - return 0; - - error_xenbus: - xenbus_transaction_end(xbt, 1); - xenbus_dev_fatal(dev, ret, "writing xenstore"); -+ unbind_irq: -+ unbind_from_irqhandler(irq, info); - return ret; - } - --- -1.7.3.4 - - -From 58b70037b6eab3520bd875d352afbefdb3949dd8 Mon Sep 17 00:00:00 2001 -From: Joe Jin -Date: Fri, 7 Jan 2011 14:50:12 +0800 -Subject: [PATCH 6/6] xen/event: validate irq before get evtchn by irq - -When retrieving the event channel number from irq, the irq -number may not be valid under some conditions. - -So far that can be when we suspend/resume and irq ends with -1. -Validate and return sanitized irq and provide diagnostics information. - -[v2: reworded the commit message] -Signed-off-by: Joe Jin -Signed-off-by: Konrad Rzeszutek Wilk -Tested-by: Gurudas Pai -Cc: Ian Campbell -Cc: Jeremy Fitzhardinge -Cc: Andrew Morton ---- - drivers/xen/events.c | 3 +++ - 1 files changed, 3 insertions(+), 0 deletions(-) - -diff --git a/drivers/xen/events.c b/drivers/xen/events.c -index 4d4a23d..25ffe12 100644 ---- a/drivers/xen/events.c -+++ b/drivers/xen/events.c -@@ -170,6 +170,9 @@ static struct irq_info *info_for_irq(unsigned irq) - - static unsigned int evtchn_from_irq(unsigned irq) - { -+ if (WARN(irq < 0 || irq >= nr_irqs, "Invalid irq %d!\n", irq)) -+ return 0; -+ - return info_for_irq(irq)->evtchn; - } - --- -1.7.3.4 - -From 2904ed8dd5a748c52caf4d8b09d3d9834b5932fa Mon Sep 17 00:00:00 2001 -From: Sheng Yang -Date: Tue, 21 Dec 2010 14:18:48 +0800 -Subject: [PATCH 1/2] apic: Move hypervisor detection of x2apic to hypervisor.h - -Then we can reuse it for Xen later. - -Acked-by: Jeremy Fitzhardinge -Acked-by: Avi Kivity -Acked-by: Ingo Molnar -Signed-off-by: Sheng Yang -Signed-off-by: Konrad Rzeszutek Wilk ---- - arch/x86/include/asm/hypervisor.h | 9 +++++++++ - arch/x86/kernel/apic/apic.c | 5 +++-- - 2 files changed, 12 insertions(+), 2 deletions(-) - -diff --git a/arch/x86/include/asm/hypervisor.h b/arch/x86/include/asm/hypervisor.h -index ff2546c..0c6f7af 100644 ---- a/arch/x86/include/asm/hypervisor.h -+++ b/arch/x86/include/asm/hypervisor.h -@@ -20,6 +20,8 @@ - #ifndef _ASM_X86_HYPERVISOR_H - #define _ASM_X86_HYPERVISOR_H - -+#include -+ - extern void init_hypervisor(struct cpuinfo_x86 *c); - extern void init_hypervisor_platform(void); - -@@ -47,4 +49,11 @@ extern const struct hypervisor_x86 x86_hyper_vmware; - extern const struct hypervisor_x86 x86_hyper_ms_hyperv; - extern const struct hypervisor_x86 x86_hyper_xen_hvm; - -+static inline bool hypervisor_x2apic_available(void) -+{ -+ if (kvm_para_available()) -+ return true; -+ return false; -+} -+ - #endif -diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c -index 3f838d5..8408f2d 100644 ---- a/arch/x86/kernel/apic/apic.c -+++ b/arch/x86/kernel/apic/apic.c -@@ -50,8 +50,8 @@ - #include - #include - #include --#include - #include -+#include - - unsigned int num_processors; - -@@ -1476,7 +1476,8 @@ void __init enable_IR_x2apic(void) - /* IR is required if there is APIC ID > 255 even when running - * under KVM - */ -- if (max_physical_apicid > 255 || !kvm_para_available()) -+ if (max_physical_apicid > 255 || -+ !hypervisor_x2apic_available()) - goto nox2apic; - /* - * without IR all CPUs can be addressed by IOAPIC/MSI --- -1.7.3.4 - - -From d9b8ca8474fd4fdd43ba6d97a4fee8b49b978067 Mon Sep 17 00:00:00 2001 -From: Sheng Yang -Date: Tue, 21 Dec 2010 14:18:49 +0800 -Subject: [PATCH 2/2] xen: HVM X2APIC support - -This patch is similiar to Gleb Natapov's patch for KVM, which enable the -hypervisor to emulate x2apic feature for the guest. By this way, the emulation -of lapic would be simpler with x2apic interface(MSR), and faster. - -[v2: Re-organized 'xen_hvm_need_lapic' per Ian Campbell suggestion] - -Acked-by: Jeremy Fitzhardinge -Signed-off-by: Sheng Yang -Signed-off-by: Konrad Rzeszutek Wilk ---- - arch/x86/include/asm/hypervisor.h | 3 ++ - arch/x86/include/asm/xen/hypervisor.h | 35 +++++++++++++++++++++++++++++++++ - arch/x86/xen/enlighten.c | 31 +++++++++++----------------- - 3 files changed, 50 insertions(+), 19 deletions(-) - -diff --git a/arch/x86/include/asm/hypervisor.h b/arch/x86/include/asm/hypervisor.h -index 0c6f7af..7a15153 100644 ---- a/arch/x86/include/asm/hypervisor.h -+++ b/arch/x86/include/asm/hypervisor.h -@@ -21,6 +21,7 @@ - #define _ASM_X86_HYPERVISOR_H - - #include -+#include - - extern void init_hypervisor(struct cpuinfo_x86 *c); - extern void init_hypervisor_platform(void); -@@ -53,6 +54,8 @@ static inline bool hypervisor_x2apic_available(void) - { - if (kvm_para_available()) - return true; -+ if (xen_x2apic_para_available()) -+ return true; - return false; - } - -diff --git a/arch/x86/include/asm/xen/hypervisor.h b/arch/x86/include/asm/xen/hypervisor.h -index 396ff4c..66d0fff 100644 ---- a/arch/x86/include/asm/xen/hypervisor.h -+++ b/arch/x86/include/asm/xen/hypervisor.h -@@ -37,4 +37,39 @@ - extern struct shared_info *HYPERVISOR_shared_info; - extern struct start_info *xen_start_info; - -+#include -+ -+static inline uint32_t xen_cpuid_base(void) -+{ -+ uint32_t base, eax, ebx, ecx, edx; -+ char signature[13]; -+ -+ for (base = 0x40000000; base < 0x40010000; base += 0x100) { -+ cpuid(base, &eax, &ebx, &ecx, &edx); -+ *(uint32_t *)(signature + 0) = ebx; -+ *(uint32_t *)(signature + 4) = ecx; -+ *(uint32_t *)(signature + 8) = edx; -+ signature[12] = 0; -+ -+ if (!strcmp("XenVMMXenVMM", signature) && ((eax - base) >= 2)) -+ return base; -+ } -+ -+ return 0; -+} -+ -+#ifdef CONFIG_XEN -+extern bool xen_hvm_need_lapic(void); -+ -+static inline bool xen_x2apic_para_available(void) -+{ -+ return xen_hvm_need_lapic(); -+} -+#else -+static inline bool xen_x2apic_para_available(void) -+{ -+ return (xen_cpuid_base() != 0); -+} -+#endif -+ - #endif /* _ASM_X86_XEN_HYPERVISOR_H */ -diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c -index 44dcad4..5b8986f 100644 ---- a/arch/x86/xen/enlighten.c -+++ b/arch/x86/xen/enlighten.c -@@ -1256,25 +1256,6 @@ asmlinkage void __init xen_start_kernel(void) - #endif - } - --static uint32_t xen_cpuid_base(void) --{ -- uint32_t base, eax, ebx, ecx, edx; -- char signature[13]; -- -- for (base = 0x40000000; base < 0x40010000; base += 0x100) { -- cpuid(base, &eax, &ebx, &ecx, &edx); -- *(uint32_t *)(signature + 0) = ebx; -- *(uint32_t *)(signature + 4) = ecx; -- *(uint32_t *)(signature + 8) = edx; -- signature[12] = 0; -- -- if (!strcmp("XenVMMXenVMM", signature) && ((eax - base) >= 2)) -- return base; -- } -- -- return 0; --} -- - static int init_hvm_pv_info(int *major, int *minor) - { - uint32_t eax, ebx, ecx, edx, pages, msr, base; -@@ -1384,6 +1365,18 @@ static bool __init xen_hvm_platform(void) - return true; - } - -+bool xen_hvm_need_lapic(void) -+{ -+ if (xen_pv_domain()) -+ return false; -+ if (!xen_hvm_domain()) -+ return false; -+ if (xen_feature(XENFEAT_hvm_pirqs) && xen_have_vector_callback) -+ return false; -+ return true; -+} -+EXPORT_SYMBOL_GPL(xen_hvm_need_lapic); -+ - const __refconst struct hypervisor_x86 x86_hyper_xen_hvm = { - .name = "Xen HVM", - .detect = xen_hvm_platform, --- -1.7.3.4 - From 105aad363797212fbd2a4c887b723407c5851175 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Thu, 9 Dec 2010 15:01:11 -0500 @@ -1135,3 +672,17 @@ index edc140a..bbdd982 100644 -- 1.7.3.4 +--- a/arch/x86/xen/setup.c 2011-01-05 00:50:19.000000000 +0000 ++++ b/arch/x86/xen/setup.c 2011-01-24 20:29:23.000000000 +0000 +@@ -179,7 +179,10 @@ + e820.nr_map = 0; + xen_extra_mem_start = mem_end; + for (i = 0; i < memmap.nr_entries; i++) { +- unsigned long long end = map[i].addr + map[i].size; ++ unsigned long long end; ++ if (map[i].type == E820_RAM) ++ map[i].size &= ~(PAGE_SIZE-1); ++ end = map[i].addr + map[i].size; + + if (map[i].type == E820_RAM && end > mem_end) { + /* RAM off the end - may be partially included */