Merge tag 'stable/for-linus-3.7-rc0-tag' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 12 Oct 2012 13:20:28 +0000 (22:20 +0900)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 12 Oct 2012 13:20:28 +0000 (22:20 +0900)
Pull Xen fixes from Konrad Rzeszutek Wilk:
 "This has four bug-fixes and one tiny feature that I forgot to put
  initially in my tree due to oversight.

  The feature is for kdump kernels to speed up the /proc/vmcore reading.
  There is a ram_is_pfn helper function that the different platforms can
  register for.  We are now doing that.

  The bug-fixes cover some embarrassing struct pv_cpu_ops variables
  being set to NULL on Xen (but not baremetal).  We had a similar issue
  in the past with {write|read}_msr_safe and this fills the three
  missing ones.  The other bug-fix is to make the console output (hvc)
  be capable of dealing with misbehaving backends and not fall flat on
  its face.  Lastly, a quirk for older XenBus implementations that came
  with an ancient v3.4 hypervisor (so RHEL5 based) - reading of certain
  non-existent attributes just hangs the guest during bootup - so we
  take precaution of not doing that on such older installations.

  Feature:
   - Register a pfn_is_ram helper to speed up reading of /proc/vmcore.
  Bug-fixes:
   - Three pvops call for Xen were undefined causing BUG_ONs.
   - Add a quirk so that the shutdown watches (used by kdump) are not
     used with older Xen (3.4).
   - Fix ungraceful state transition for the HVC console."

* tag 'stable/for-linus-3.7-rc0-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen:
  xen/pv-on-hvm kexec: add quirk for Xen 3.4 and shutdown watches.
  xen/bootup: allow {read|write}_cr8 pvops call.
  xen/bootup: allow read_tscp call for Xen PV guests.
  xen pv-on-hvm: add pfn_is_ram helper for kdump
  xen/hvc: handle backend CLOSED without CLOSING

arch/x86/xen/enlighten.c
arch/x86/xen/mmu.c
drivers/tty/hvc/hvc_xen.c
drivers/xen/xenbus/xenbus_xs.c
include/xen/interface/hvm/hvm_op.h

index bf788d34530df5fbb93e60bb64023d80f7bbedf3..e3497f240eabb869e6cda863036689e6b093899d 100644 (file)
@@ -987,7 +987,16 @@ static void xen_write_cr4(unsigned long cr4)
 
        native_write_cr4(cr4);
 }
-
+#ifdef CONFIG_X86_64
+static inline unsigned long xen_read_cr8(void)
+{
+       return 0;
+}
+static inline void xen_write_cr8(unsigned long val)
+{
+       BUG_ON(val);
+}
+#endif
 static int xen_write_msr_safe(unsigned int msr, unsigned low, unsigned high)
 {
        int ret;
@@ -1156,6 +1165,11 @@ static const struct pv_cpu_ops xen_cpu_ops __initconst = {
        .read_cr4_safe = native_read_cr4_safe,
        .write_cr4 = xen_write_cr4,
 
+#ifdef CONFIG_X86_64
+       .read_cr8 = xen_read_cr8,
+       .write_cr8 = xen_write_cr8,
+#endif
+
        .wbinvd = native_wbinvd,
 
        .read_msr = native_read_msr_safe,
@@ -1164,6 +1178,8 @@ static const struct pv_cpu_ops xen_cpu_ops __initconst = {
        .read_tsc = native_read_tsc,
        .read_pmc = native_read_pmc,
 
+       .read_tscp = native_read_tscp,
+
        .iret = xen_iret,
        .irq_enable_sysexit = xen_sysexit,
 #ifdef CONFIG_X86_64
index fd28d86fe3d2c979c5c9ac0e5ab95bf3d977a224..6226c99729b963594a2e133290cbf8f3c6e681b8 100644 (file)
@@ -47,6 +47,7 @@
 #include <linux/gfp.h>
 #include <linux/memblock.h>
 #include <linux/seq_file.h>
+#include <linux/crash_dump.h>
 
 #include <trace/events/xen.h>
 
@@ -2381,6 +2382,43 @@ void xen_destroy_contiguous_region(unsigned long vstart, unsigned int order)
 EXPORT_SYMBOL_GPL(xen_destroy_contiguous_region);
 
 #ifdef CONFIG_XEN_PVHVM
+#ifdef CONFIG_PROC_VMCORE
+/*
+ * This function is used in two contexts:
+ * - the kdump kernel has to check whether a pfn of the crashed kernel
+ *   was a ballooned page. vmcore is using this function to decide
+ *   whether to access a pfn of the crashed kernel.
+ * - the kexec kernel has to check whether a pfn was ballooned by the
+ *   previous kernel. If the pfn is ballooned, handle it properly.
+ * Returns 0 if the pfn is not backed by a RAM page, the caller may
+ * handle the pfn special in this case.
+ */
+static int xen_oldmem_pfn_is_ram(unsigned long pfn)
+{
+       struct xen_hvm_get_mem_type a = {
+               .domid = DOMID_SELF,
+               .pfn = pfn,
+       };
+       int ram;
+
+       if (HYPERVISOR_hvm_op(HVMOP_get_mem_type, &a))
+               return -ENXIO;
+
+       switch (a.mem_type) {
+               case HVMMEM_mmio_dm:
+                       ram = 0;
+                       break;
+               case HVMMEM_ram_rw:
+               case HVMMEM_ram_ro:
+               default:
+                       ram = 1;
+                       break;
+       }
+
+       return ram;
+}
+#endif
+
 static void xen_hvm_exit_mmap(struct mm_struct *mm)
 {
        struct xen_hvm_pagetable_dying a;
@@ -2411,6 +2449,9 @@ void __init xen_hvm_init_mmu_ops(void)
 {
        if (is_pagetable_dying_supported())
                pv_mmu_ops.exit_mmap = xen_hvm_exit_mmap;
+#ifdef CONFIG_PROC_VMCORE
+       register_oldmem_pfn_is_ram(&xen_oldmem_pfn_is_ram);
+#endif
 }
 #endif
 
index 2944ff88fdc0b2ea9705850e080a755aca440a8d..f4abfe238f98cb6bb6a4c53607bd4adf2a447ebc 100644 (file)
@@ -478,7 +478,6 @@ static void xencons_backend_changed(struct xenbus_device *dev,
        case XenbusStateInitialising:
        case XenbusStateInitialised:
        case XenbusStateUnknown:
-       case XenbusStateClosed:
                break;
 
        case XenbusStateInitWait:
@@ -488,6 +487,10 @@ static void xencons_backend_changed(struct xenbus_device *dev,
                xenbus_switch_state(dev, XenbusStateConnected);
                break;
 
+       case XenbusStateClosed:
+               if (dev->state == XenbusStateClosed)
+                       break;
+               /* Missed the backend's CLOSING state -- fallthrough */
        case XenbusStateClosing:
                xenbus_frontend_closed(dev);
                break;
index 131dec04794ee3ee1af70c2fd3f1dd2220774070..48220e129f854435292065c5e928f95d982a4ad3 100644 (file)
@@ -48,6 +48,7 @@
 #include <xen/xenbus.h>
 #include <xen/xen.h>
 #include "xenbus_comms.h"
+#include <asm/xen/hypervisor.h>
 
 struct xs_stored_msg {
        struct list_head list;
@@ -618,7 +619,24 @@ static struct xenbus_watch *find_watch(const char *token)
 
        return NULL;
 }
+/*
+ * Certain older XenBus toolstack cannot handle reading values that are
+ * not populated. Some Xen 3.4 installation are incapable of doing this
+ * so if we are running on anything older than 4 do not attempt to read
+ * control/platform-feature-xs_reset_watches.
+ */
+static bool xen_strict_xenbus_quirk()
+{
+       uint32_t eax, ebx, ecx, edx, base;
+
+       base = xen_cpuid_base();
+       cpuid(base + 1, &eax, &ebx, &ecx, &edx);
 
+       if ((eax >> 16) < 4)
+               return true;
+       return false;
+
+}
 static void xs_reset_watches(void)
 {
        int err, supported = 0;
@@ -626,6 +644,9 @@ static void xs_reset_watches(void)
        if (!xen_hvm_domain() || xen_initial_domain())
                return;
 
+       if (xen_strict_xenbus_quirk())
+               return;
+
        err = xenbus_scanf(XBT_NIL, "control",
                        "platform-feature-xs_reset_watches", "%d", &supported);
        if (err != 1 || !supported)
index a4827f46ee97fffd0021874dabc49877ae67ca4b..956a04682865bbf19b456448b83af6112240dd6f 100644 (file)
@@ -43,4 +43,23 @@ struct xen_hvm_pagetable_dying {
 typedef struct xen_hvm_pagetable_dying xen_hvm_pagetable_dying_t;
 DEFINE_GUEST_HANDLE_STRUCT(xen_hvm_pagetable_dying_t);
  
+enum hvmmem_type_t {
+    HVMMEM_ram_rw,             /* Normal read/write guest RAM */
+    HVMMEM_ram_ro,             /* Read-only; writes are discarded */
+    HVMMEM_mmio_dm,            /* Reads and write go to the device model */
+};
+
+#define HVMOP_get_mem_type    15
+/* Return hvmmem_type_t for the specified pfn. */
+struct xen_hvm_get_mem_type {
+    /* Domain to be queried. */
+    domid_t domid;
+    /* OUT variable. */
+    uint16_t mem_type;
+    uint16_t pad[2]; /* align next field on 8-byte boundary */
+    /* IN variable. */
+    uint64_t pfn;
+};
+DEFINE_GUEST_HANDLE_STRUCT(xen_hvm_get_mem_type);
+
 #endif /* __XEN_PUBLIC_HVM_HVM_OP_H__ */