]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge tag 'stable/for-linus-3.10-rc0-tag-two' of git://git.kernel.org/pub/scm/linux...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 11 May 2013 23:19:30 +0000 (16:19 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 11 May 2013 23:19:30 +0000 (16:19 -0700)
Pull Xen bug-fixes from Konrad Rzeszutek Wilk:
 - More fixes in the vCPU PVHVM hotplug path.
 - Add more documentation.
 - Fix various ARM related issues in the Xen generic drivers.
 - Updates in the xen-pciback driver per Bjorn's updates.
 - Mask the x2APIC feature for PV guests.

* tag 'stable/for-linus-3.10-rc0-tag-two' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen:
  xen/pci: Used cached MSI-X capability offset
  xen/pci: Use PCI_MSIX_TABLE_BIR, not PCI_MSIX_FLAGS_BIRMASK
  xen: clear IRQ_NOAUTOEN and IRQ_NOREQUEST
  xen: mask x2APIC feature in PV
  xen: SWIOTLB is only used on x86
  xen/spinlock: Fix check from greater than to be also be greater or equal to.
  xen/smp/pvhvm: Don't point per_cpu(xen_vpcu, 33 and larger) to shared_info
  xen/vcpu: Document the xen_vcpu_info and xen_vcpu
  xen/vcpu/pvhvm: Fix vcpu hotplugging hanging.

1  2 
arch/x86/xen/enlighten.c
drivers/xen/Kconfig
drivers/xen/events.c

diff --combined arch/x86/xen/enlighten.c
index 53d4f680c9b59f498d41148325cd5a96ef1723e3,4bd0066a1ef05026eee9c908652eb6bafbf42668..a492be2635ac048a527d856b796431ccac72d9fd
  
  EXPORT_SYMBOL_GPL(hypercall_page);
  
+ /*
+  * Pointer to the xen_vcpu_info structure or
+  * &HYPERVISOR_shared_info->vcpu_info[cpu]. See xen_hvm_init_shared_info
+  * and xen_vcpu_setup for details. By default it points to share_info->vcpu_info
+  * but if the hypervisor supports VCPUOP_register_vcpu_info then it can point
+  * to xen_vcpu_info. The pointer is used in __xen_evtchn_do_upcall to
+  * acknowledge pending events.
+  * Also more subtly it is used by the patched version of irq enable/disable
+  * e.g. xen_irq_enable_direct and xen_iret in PV mode.
+  *
+  * The desire to be able to do those mask/unmask operations as a single
+  * instruction by using the per-cpu offset held in %gs is the real reason
+  * vcpu info is in a per-cpu pointer and the original reason for this
+  * hypercall.
+  *
+  */
  DEFINE_PER_CPU(struct vcpu_info *, xen_vcpu);
+ /*
+  * Per CPU pages used if hypervisor supports VCPUOP_register_vcpu_info
+  * hypercall. This can be used both in PV and PVHVM mode. The structure
+  * overrides the default per_cpu(xen_vcpu, cpu) value.
+  */
  DEFINE_PER_CPU(struct vcpu_info, xen_vcpu_info);
  
  enum xen_domain_type xen_domain_type = XEN_NATIVE;
@@@ -157,6 -179,21 +179,21 @@@ static void xen_vcpu_setup(int cpu
  
        BUG_ON(HYPERVISOR_shared_info == &xen_dummy_shared_info);
  
+       /*
+        * This path is called twice on PVHVM - first during bootup via
+        * smp_init -> xen_hvm_cpu_notify, and then if the VCPU is being
+        * hotplugged: cpu_up -> xen_hvm_cpu_notify.
+        * As we can only do the VCPUOP_register_vcpu_info once lets
+        * not over-write its result.
+        *
+        * For PV it is called during restore (xen_vcpu_restore) and bootup
+        * (xen_setup_vcpu_info_placement). The hotplug mechanism does not
+        * use this function.
+        */
+       if (xen_hvm_domain()) {
+               if (per_cpu(xen_vcpu, cpu) == &per_cpu(xen_vcpu_info, cpu))
+                       return;
+       }
        if (cpu < MAX_VIRT_CPUS)
                per_cpu(xen_vcpu,cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu];
  
  
        /* Check to see if the hypervisor will put the vcpu_info
           structure where we want it, which allows direct access via
-          a percpu-variable. */
+          a percpu-variable.
+          N.B. This hypercall can _only_ be called once per CPU. Subsequent
+          calls will error out with -EINVAL. This is due to the fact that
+          hypervisor has no unregister variant and this hypercall does not
+          allow to over-write info.mfn and info.offset.
+        */
        err = HYPERVISOR_vcpu_op(VCPUOP_register_vcpu_info, cpu, &info);
  
        if (err) {
@@@ -387,6 -429,9 +429,9 @@@ static void __init xen_init_cpuid_mask(
                cpuid_leaf1_edx_mask &=
                        ~((1 << X86_FEATURE_APIC) |  /* disable local APIC */
                          (1 << X86_FEATURE_ACPI));  /* disable ACPI */
+       cpuid_leaf1_ecx_mask &= ~(1 << (X86_FEATURE_X2APIC % 32));
        ax = 1;
        cx = 0;
        xen_cpuid(&ax, &bx, &cx, &dx);
@@@ -1221,6 -1266,7 +1266,6 @@@ static const struct pv_cpu_ops xen_cpu_
        .alloc_ldt = xen_alloc_ldt,
        .free_ldt = xen_free_ldt,
  
 -      .store_gdt = native_store_gdt,
        .store_idt = native_store_idt,
        .store_tr = xen_store_tr,
  
@@@ -1603,6 -1649,9 +1648,9 @@@ void __ref xen_hvm_init_shared_info(voi
         * online but xen_hvm_init_shared_info is run at resume time too and
         * in that case multiple vcpus might be online. */
        for_each_online_cpu(cpu) {
+               /* Leave it to be NULL. */
+               if (cpu >= MAX_VIRT_CPUS)
+                       continue;
                per_cpu(xen_vcpu, cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu];
        }
  }
diff --combined drivers/xen/Kconfig
index dd4d9cb862432b4ce6715aba3164a53ffaaa87a5,ed6a8099666d1b2e73fdd9f29ac395bdc261e5d6..f03bf501527f64785a3fbbec39963f979d70ad8a
@@@ -141,13 -141,13 +141,13 @@@ config XEN_GRANT_DEV_ALLO
  
  config SWIOTLB_XEN
        def_bool y
-       depends on PCI
+       depends on PCI && X86
        select SWIOTLB
  
  config XEN_TMEM
 -      bool
 +      tristate
        depends on !ARM
 -      default y if (CLEANCACHE || FRONTSWAP)
 +      default m if (CLEANCACHE || FRONTSWAP)
        help
          Shim to interface in-kernel Transcendent Memory hooks
          (e.g. cleancache and frontswap) to Xen tmem hypercalls.
diff --combined drivers/xen/events.c
index d8cc8127f19c18f9b6a4ea9f937015363b912bd8,b6c4f1a6d1e281706ac63fb2bdaa82763e1c9943..6a6bbe4ede92c67afe4c88efd105839f14b3a240
@@@ -167,6 -167,8 +167,8 @@@ static void xen_irq_info_common_init(st
        info->cpu = cpu;
  
        evtchn_to_irq[evtchn] = irq;
+       irq_clear_status_flags(irq, IRQ_NOREQUEST|IRQ_NOAUTOEN);
  }
  
  static void xen_irq_info_evtchn_init(unsigned irq,
@@@ -874,7 -876,6 +876,6 @@@ int bind_evtchn_to_irq(unsigned int evt
                struct irq_info *info = info_for_irq(irq);
                WARN_ON(info == NULL || info->type != IRQT_EVTCHN);
        }
-       irq_clear_status_flags(irq, IRQ_NOREQUEST|IRQ_NOAUTOEN);
  
  out:
        mutex_unlock(&irq_mapping_update_lock);
@@@ -1321,7 -1322,7 +1322,7 @@@ static void __xen_evtchn_do_upcall(void
  {
        int start_word_idx, start_bit_idx;
        int word_idx, bit_idx;
 -      int i;
 +      int i, irq;
        int cpu = get_cpu();
        struct shared_info *s = HYPERVISOR_shared_info;
        struct vcpu_info *vcpu_info = __this_cpu_read(xen_vcpu);
  
        do {
                xen_ulong_t pending_words;
 +              xen_ulong_t pending_bits;
 +              struct irq_desc *desc;
  
                vcpu_info->evtchn_upcall_pending = 0;
  
                 * selector flag. xchg_xen_ulong must contain an
                 * appropriate barrier.
                 */
 +              if ((irq = per_cpu(virq_to_irq, cpu)[VIRQ_TIMER]) != -1) {
 +                      int evtchn = evtchn_from_irq(irq);
 +                      word_idx = evtchn / BITS_PER_LONG;
 +                      pending_bits = evtchn % BITS_PER_LONG;
 +                      if (active_evtchns(cpu, s, word_idx) & (1ULL << pending_bits)) {
 +                              desc = irq_to_desc(irq);
 +                              if (desc)
 +                                      generic_handle_irq_desc(irq, desc);
 +                      }
 +              }
 +
                pending_words = xchg_xen_ulong(&vcpu_info->evtchn_pending_sel, 0);
  
                start_word_idx = __this_cpu_read(current_word_idx);
                word_idx = start_word_idx;
  
                for (i = 0; pending_words != 0; i++) {
 -                      xen_ulong_t pending_bits;
                        xen_ulong_t words;
  
                        words = MASK_LSBS(pending_words, word_idx);
  
                        do {
                                xen_ulong_t bits;
 -                              int port, irq;
 -                              struct irq_desc *desc;
 +                              int port;
  
                                bits = MASK_LSBS(pending_bits, bit_idx);